年轻人的编程

时间:2013-03-29 14:13:13

标签: c prolog clpfd constraint-programming diagrams

一个奇怪的问题如下:
我正在为我的学校解决竞争问题,他们允许我们使用电脑。由于我是竞赛中唯一知道如何编码的人,我使用C和Pascal程序来更快地解决问题。我已经完成了伪代码到代码练习,算法,Collat​​z猜想验证等。
现在,昨天我正在接受下一次挑战训练(4月18日),我看到了一场关于Young tableaux的练习。它是这样措辞(我会尽力翻译意大利语):
“Ferrers图是N个盒子的配置,分布在一个或多个水平行中,左对齐并配置成每行包含的行数等于或低于其上的行数。这些配置也可能由一个列表描述。方框号码,如下图所示:
ferrers diagrams http://olimpiadiproblemsolving.it/immagini_test/mate/finale_2011_m_07a_400.jpg
Young画面是N个盒子的Ferrers图,其中填充了从1到N的整数。例如:
young tableaux http://olimpiadiproblemsolving.it/immagini_test/mate/finale_2011_s_03b_400.jpg
如果对框中的数字进行排序,使得它们按行和按列递增,则该表为“标准”(例如:第一,第三和第五个画面)。在标准表格中,第一行的第一个框始终包含1.N始终位于图表的其中一行的最左侧框中。


问题

考虑[6,3,2,1,1,1] Ferrers图:
1)如果第1行的第6个框中固定了6个,第1列的最后一个框中固定了11个,那么您可以用多少种方式以标准方式完成图表?

2)如果第一排的第6个方框上固定了7个,第一列的最后一个方框中固定了11个,那么您可以用多少种方式以标准方式完成图表?

3)如果第1行的第6个框中固定了8个,第1列的最后一个框中固定了11个,那么以标准方式完成图表的方式有多少?“

我试图用一个填充了这些数字的矩阵和一个“-1”作为“行尾字符”来编写解决方案,但是我被卡住了。我如何编码“以各种可能的方式填写它以使画面成为标准?”。

5 个答案:

答案 0 :(得分:5)

以下是使用SWI-Prolog解决第一个问题的示例解决方案:

:- use_module(library(clpfd)).

tableau(Ts) :-
        Ts = [[A,B,C,_,_,F],
              [G,H,I],
              [J,K],
              [L],
              [M],
              [N]],
        A = 1,
        maplist(ascending, Ts),
        ascending([A,G,J,L,M,N]),
        ascending([B,H,K]),
        C #< I,
        append(Ts, Vs),
        all_different(Vs),
        Vs ins 1..14,
        F = 6,
        N = 11,
        label(Vs).

ascending(Vs) :- chain(Vs, #<).

答案是有两种方法可以完成画面:

?- tableau(Ts), maplist(writeln, Ts).
[1,2,3,4,5,6]
[7,12,13]
[8,14]
[9]
[10]
[11]
    Ts = [[1, 2, 3, 4, 5, 6], [7, 12, 13], [8, 14], [9], [10], [11]] ;
[1,2,3,4,5,6]
[7,12,14]
[8,13]
[9]
[10]
[11]
    Ts = [[1, 2, 3, 4, 5, 6], [7, 12, 14], [8, 13], [9], [10], [11]] ;
false.

答案 1 :(得分:3)

要解决这个问题,我会使用Constraint Programming(CP)。在学习新的CP系统时,Young tableaux实际上是我试图解决的标准问题之一。以下是目前为止的实施列表:http://hakank.org/common_cp_models/#youngtableaux

我已经更改了“普通”MiniZinc模型,并针对您的具体问题提供了一些额外的限制。在这里查看完整模型:      http://www.hakank.org/minizinc/young_tableaux_stack_overflow.mzn

(MiniZinc非常高,很容易尝试这样的问题。)

简短介绍模型中的表示: 对于大小为n(n的分区)的问题,方框表示为网格(“x”,大小为n次n),其值为1到n + 1,其中每个行和列按递增顺序排序;所以n + 1最后排序并充当空值。然后处理分区结构(“p”)以符合Young / Ferrer结构(详见模型)。

这三个问题中的每一个都有两个额外的限制(与问题的标准表述相比):

  • 某个数字应该在第一行的第6个框中  增加的约束是       x [1,6] = 6%或7或8

  • 和11应位于第一列的最后一个框中  这有点棘手,但我的方式就是这个,即  在第一列11中应该是小于n + 1的最后一个值,  即列中的所有值均为n + 1:

     exists(j in 1..n) (
          x[j,1] = 11 /\ forall(k in j+1..n) (x[k,1] = n+1)
     )
    

所以,如果我正确理解了问题,答案是:   1)2个解决方案   2)10个解决方案   3)30个解决方案

答案 2 :(得分:1)

在不使用程序的情况下,我相信1)的答案是2.手工推导可能会导致某人使用算法解决方案。

第一行以1开头并以6结尾。因此,可以进入第1行的数字必须满足以下条件:1&lt; x&lt; 6.在这个表格中可以进入的14个数字中,只有4个满足该条件,它们是:2 3 4 5.这意味着第1行必须是:1 2 3 4 5 6。

第一列以1开头并以11结尾。可以进入第一列的数字必须满足类似的条件:1&lt; y&lt; 11.在剩余的未分配数字中,只有4个符合这一条件:7 8 9 10.这导致第一列为:1 7 8 9 10 11.

现在只剩下3个数字:12 13 14.只有两种方法可以在其余的3个单元格中排列它们。他们可以安排:

12 13

14

- 或 -

12 14

13

尝试在代码中解决这个问题,可以选择强力路线,或者研究约束传播和回溯技术。这就是为什么有人早些时候建议Prolog。要看的另一种语言是Python。

答案 3 :(得分:0)

这是一个Constraint逻辑编程问题。使用编程语言Prolog。使用clpfd库的Sicstus prolog。

考虑这样的布局:

ABCDEF
GHI
JK
L
M
N

- 代码 -

use_module(library(clpfd)).

all_different([A,B,C,D,E,F,G,H,I,J,K,L,M,N]),
domain([A,B,C,D,E,F,G,H,I,J,K,L,M,N],1,14),
B #> A, C #> B, D #> C, E #> D, F #> E,
G #> A, H #> B, H #> G, I #> G, I #> H,  I #> C,
J #> A, J #> G, 
L #> A, L #> G, L #> J,
M #> A, M #> G, M #> J, M #> L,
N #> A, N #> G, N #> J, N #> L, N #> M.

A=1
F=6
N=11

答案 4 :(得分:0)

这是著名的科门著作的练习。我发现this resource有助于学习此问题,并进行这种结构的构造,提取min元素,并按原样维护数据结构。