我是约束编程的新手(来自 c#),我正在尝试解决这个问题。不幸的是,我没有这种拼图的名字,所以我不确定要搜索什么。我能找到的最接近的例子是 Nonogram 和 Tomography 谜题。
谜题描述:给玩家一个空的游戏板(大小不一),他们必须用 n 种颜色填充,使用线索模式作为行和列。每个线索模式是该行/列中的颜色序列,但删除了连续的重复项。
这是一个简单的 4x4 小网格示例,具有 3 种颜色:
rbg,rbr,grb,bgbg <- (top-to-bottom column constraints)
_,_,_,_ rgb <- (row constraints)
_,_,_,_ brg
_,_,_,_ b
_,_,_,_ grbg
解决方案(2):
r,r,g,b
b,?,r,g
b,b,b,b
g,r,b,g
? 可以是红色或蓝色,但不能是绿色。
下面的模式示例。给定 6 长度序列的示例:
aaaaaa -> a
aabbcc -> abc
abbbbc -> abc
cabbbc -> cabc
bbbaac -> bac
abbaab -> abab
abcabc -> abcabc
给出潜在解决方案序列模式的示例:
abc -> abc (3 length solution)
abc -> abcc, abbc, aabc (4 length solutions)
abc -> abccc, abbcc, abbbc, aabbc, aaabc (5 length solutions)
我试图在 C# or-tools 和 MiniZinc 中解决它,但我遇到的最大问题是构建约束。我可以从一个序列中生成模式(以 c# 命令式的方式),但是如何将它变成一个约束呢?
我的想法是:从每个线索模式中生成所有潜在的序列。然后对相应的行/列进行约束,说明它必须是这些序列之一。
上面拼图中顶行的示例:rgb to [4-length sequences] -> rgbb, rggb, rrgb,然后为该行添加一个约束:必须等于这些序列之一。
我在想这个吗?有什么更聪明的方法吗?
感谢您的任何建议。
======================================
取得一些进展后进行编辑:
这个 MiniZinc 正确地解决了模式 abc 的顶行,它有 3 个 4 长度的解决方案:aabc、abbc、abcc。
include "globals.mzn";
array [1..4, 1..4] of var 1..3: colors;
constraint regular(row(colors, 1), 4, 3,
[|
% a, b, c
2,0,0| % accept 'a'
2,3,0| % accept 'a' or 'b' ?
0,3,4| % accept 'b' or 'c' ?
0,0,4| % accept 'c'
|], 1, {4});
% Don't care about rest of grid for now.
constraint forall(i,j in 1..4 where i > 1) (row(colors, i)[j] = 1);
solve satisfy;
output [show(colors)];
但是,我不确定如何处理具有许多模式的较大网格,而不是像这样对所有内容进行硬编码。我会多做一些实验。