构建 4×4 拉丁方格:为颜色与情绪生成无重复行列的组合矩阵

云涛吖_7629

云涛吖_7629

2026-10-24

662人浏览

原创

构建 4×4 拉丁方格:为颜色与情绪生成无重复行列的组合矩阵

本文介绍如何用回溯算法生成一个 4×4 的拉丁方格(latin square),确保每行每列中颜色和情绪均不重复,适用于配对约束类布局问题。

本文介绍如何用回溯算法生成一个 4×4 的拉丁方格(latin square),确保每行每列中颜色和情绪均不重复,适用于配对约束类布局问题。

该问题本质是构造一个双约束拉丁方格(Graeco-Latin Square):给定两个大小均为 $n=4$ 的集合(颜色、情绪),需将全部 $n^2=16$ 个唯一配对填入 $n \times n$ 网格,使得每一行和每一列中:

  • 所有颜色互不相同;
  • 所有情绪互不相同。

这等价于同时满足两个正交拉丁方——即颜色构成一个拉丁方,情绪也构成一个拉丁方,且二者正交(每对 (color, emotion) 恰好出现一次)。对于 $n=4$,这样的正交拉丁方组是存在的(事实上,所有 $n \neq 2,6$ 均存在,而 $n=4$ 有多个解)。

以下是一个完整、可运行的 PHP 教程实现,采用递归回溯 + 冲突检测策略:

✅ 核心思路

  1. 预生成所有配对:枚举 $colors × $emotions 得到 16 个 [color, emotion] 元组;
  2. 按顺序尝试填充网格:从左上角 (0,0) 开始,逐格尝试未使用过的配对;
  3. 冲突检测(关键):在填入前检查目标行列是否已含相同 color 或 emotion;
  4. 回溯机制:若某位置无法填入合法配对,则撤销上一步,尝试其他选项。

? 关键函数详解

noCollision($element, $row, $col, $grid)

判断将配对 $element = [$color, $emotion] 放入第 $row 行、$col 列是否合法:

function noCollision($element, $row, $col, $grid) {
    // 检查行冲突:同一行不能重复 color 或 emotion
    $rowSet = [];
    foreach ($grid[$row] as $cell) {
        if (!empty($cell)) {
            $rowSet[$cell[0]] = true; // color
            $rowSet[$cell[1]] = true; // emotion
        }
    }
    if (isset($rowSet[$element[0]]) || isset($rowSet[$element[1]])) {
        return false;
    }

    // 检查列冲突
    $colSet = [];
    foreach ($grid as $r => $rowArr) {
        if (!empty($rowArr[$col])) {
            $colSet[$rowArr[$col][0]] = true; // color
            $colSet[$rowArr[$col][1]] = true; // emotion
        }
    }
    return !isset($colSet[$element[0]]) && !isset($colSet[$element[1]]);
}

⚠️ 注意:此处将 color 和 emotion 统一视为“符号”加入同一哈希集检测,因二者值域无交集(如 'gold' 与 'happy' 不同名),故不会误判。

makeGrid($combs, &$grid, $idx, $total)

标准回溯主逻辑:尝试将第 $idx 个配对填入第一个空位。

function makeGrid($combs, &$grid, $idx, $total) {
    if ($idx === $total) return true; // 全部填完,成功

    $n = count($grid);
    for ($i = 0; $i <h4><code>generateGrid($colors, $emotions, &$grid)</code></h4><p>初始化网格并启动回溯:</p><pre class="brush:php;toolbar:false;">function generateGrid($colors, $emotions, &$grid) {
    // 生成全部配对
    $combs = [];
    foreach ($colors as $c) {
        foreach ($emotions as $e) {
            $combs[] = [$c, $e];
        }
    }

    // 初始化 n×n 空网格
    $n = count($colors);
    $grid = array_fill(0, $n, array_fill(0, $n, []));

    // 启动回溯
    if (makeGrid($combs, $grid, 0, $n * $n)) {
        return true;
    }

    $grid = []; // 失败则重置
    return false;
}

▶️ 使用示例

$colors   = ['gold', 'silver', 'bronze', 'wood'];
$emotions = ['happy', 'sad', 'wow', 'angry'];

$grid = [];
if (generateGrid($colors, $emotions, $grid)) {
    // 格式化输出为关联数组:['color' => 'emotion']
    $result = [];
    foreach ($grid as $i => $row) {
        $result[$i] = [];
        foreach ($row as $pair) {
            if (!empty($pair)) {
                $result[$i][$pair[0]] = $pair[1];
            }
        }
    }
    print_r($result);
} else {
    echo "No valid grid found.\n";
}

? 输出结构说明

最终 $result 是一个四维数组,每个子数组长度为 4,键为颜色、值为对应情绪,严格满足:

  • 每行:4 个不同颜色 + 4 个不同情绪;
  • 每列:4 个不同颜色 + 4 个不同情绪;
  • 全局:16 种 (color, emotion) 组合各出现一次。

? 性能与扩展提示

  • 时间复杂度:最坏 $O((n^2)!)$,但剪枝高效,$n=4$ 瞬间完成;
  • 可扩展至 $n=5$(仍可行),$n=6$ 无解(Euler 三十六军官问题);
  • 若需所有解,可修改 makeGrid 中 return true 为收集结果并继续回溯;
  • 如需随机解,可在 foreach ($combs as ...) 前 shuffle($combs)。

此方案兼具理论严谨性与工程实用性,是解决正交配对布局问题的经典范式。

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
Gradle插件开发入门教程
Gradle插件开发入门教程

本专题介绍Gradle插件开发的基本流程,涵盖插件类编写、自定义任务注册、扩展参数设计和插件应用方法,帮助你理解插件如何组织构建逻辑,减少多个项目之间的重复配置。

2026.10.22

20

11

Gradle Wrapper配置教程
Gradle Wrapper配置教程

本专题介绍Gradle Wrapper的基本作用,涵盖文件组成、生成方法、版本配置和任务调用,帮助你理解项目如何使用指定的Gradle版本,减少不同开发环境带来的构建差异。

2026.10.22

20

10

Golangci-lint检查器使用教程
Golangci-lint检查器使用教程

本专题整理Golangci-lint常用Linters的用途与配置方法,覆盖错误处理、无效代码、安全、复杂度、命名和依赖检查,帮助项目合理选规则。

2026.10.22

20

15

Gradle怎么构建Java项目
Gradle怎么构建Java项目

本专题介绍Gradle Java项目构建方法,涵盖Java插件配置、依赖声明、源码编译、测试执行和打包检查,帮助你理解各阶段的任务关系,逐步完成项目构建。

2026.10.22

0

10

PHP时间戳漏洞修复教程
PHP时间戳漏洞修复教程

本专题汇总PHP常见时间戳漏洞,包括2038年溢出、时区漂移、时间戳伪造、重放攻击、时间盲注与日志审计失效等,并给出升级64位环境、使用 DateTimeImmutable、统一UTC、严格超时校验、预处理绑定、hash_equals 比对等修复方案,帮助开发者快速排查和加固时间相关代码。

2026.10.22

20

25

Golangci-lint配置文件与规则设置
Golangci-lint配置文件与规则设置

本专题聚焦Golangci-lint YAML配置文件,讲清运行参数、规则启停、目录排除、问题过滤及严重级别设置,便于团队统一检查标准。

2026.10.22

20

15

Golangci-lint安装与入门教程
Golangci-lint安装与入门教程

本专题讲解Golangci-lint的安装、初始化、基础命令和首次代码检查,覆盖本地环境、Docker及多平台用法,帮助Go开发者快速上手。

2026.10.22

20

15

PHP2Shell高危漏洞修复教程
PHP2Shell高危漏洞修复教程

PHP2Shell漏洞是什么,哪些PHP版本和运行环境会受到影响,服务器应该如何检测与修复?本专题提供版本自查脚本、Linux与Docker升级命令、PHP-FPM和Apache排查步骤,以及修复验证、临时缓解和应急响应方案。

2026.10.22

100

12

剧云人物设定与关系管理教程
剧云人物设定与关系管理教程

本专题介绍剧云人物设定与关系管理,讲解角色小传、性格职业、人物目标、背景资料和关系网络的创建及维护方法。

2026.10.22

20

16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.7万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 133.9万人学习