Prolog:如何将一块巧克力碎成碎片

时间:2015-01-15 03:31:04

标签: prolog logic

我有以下任务要做:

给出一个矩形巧克力棒,由m x n个小矩形组成,并希望将其分解成各个部分。在每一步中,您只能选择一件并沿其任何垂直线或沿其水平线折断。你应该如何使用最少的步骤打破巧克力棒?

我知道你需要完全m x n - 1步才能打破巧克力棒,但我被要求做“CS方式:”

定义一个谓词,用于选择将巧克力块分成碎片的所有替代可能性中的最小步数。在另一个参数位置构造一个结构,它告诉你在哪里以及如何打破这个条以及如何处理由此产生的两个部分。

我的想法:在打破一块巧克力之后,您可以选择在垂直或水平线上打破它。所以这是我的代码,但它不起作用:

break_chocolate(Horizontal, Vertical, Minimum) :-
break_horizontal(Horizontal, Vertical, Min1),
break_vertical(Horizontal, Vertical, Min2),
Minimum is min(Min1, Min2).

break_horizontal(0,0,_).
break_vertical(0,0,_).

break_horizontal(0, V, Min) :-
    V > 0,
    break_horizontal(0, V, Min).

break_horizontal(H, V, Min) :-
    H1 is H-1,
    Min1 is Min + 1,
    break_vertical(H1, V, Min1).

break_horizontal(H, V, Min) :-
    H1 is H-1,
    Min1 is Min + 1,
    break_vertical(H1, V, Min).

break_vertical(H, V, Min) :-
    V1 is V-1,
    Min1 is Min + 1,
    break_horizontal(H, V1, Min1).

break_vertical(H, V, Min) :-
    V1 is V-1,
    Min1 is Min + 1,
    break_vertical(H, V1, Min1).

break_vertical(H, 0, Min) :-
    H > 0,
    break_horizontal(H, 0, Min).

有人可以帮我这个吗?

3 个答案:

答案 0 :(得分:1)

这不是一个完整的答案,但应该让你朝着正确的方向前进:

首先观察一下:每当你切一块巧克力棒时,你最终会得到比以前更强的一个块。所以,实际上,你可以拥有的“最小”休息次数;你从1件(整个酒吧)开始,最后得到m * n件,所以你总是有m * n - 1个休息时间。所以要么你误解了你的问题陈述,要么在你的问题中以某种方式歪曲它。

第二:一旦你分成两部分,你将不得不打破中的每一个,就像破坏前一个一样。编程的一种方法是使用递归调用。我没有在你的程序中看到这一点,就像它一样。

第三:那么你想报告你做的休息吗?你打算怎么做?

无论您是使用Prolog,C还是JavaScript编程,了解您的问题都是找到解决方案的先决条件。

答案 1 :(得分:1)

以下是一些表示和解决问题的其他提示。

每次休息将一件作品分成两件(参见鲍里斯的第二个提示)。因此,您可以将休息集合视为具有以下特征的二元树断点:

  • 树的根节点的值为M-N(维度中的栏为M x N
  • 假设X-Y表示树中任何节点的值,表示单个X Y1-1不是单件X。由于节点的两个子节点表示维度YX-Y沿着一个维度被破坏,因此A-Y的子节点具有值B-Y和{{} 1}} A + B = X,或X-AX-B A + B = Y
  • 的值
  • 树的所有叶节点都具有值1-1(可能的最小块)

二叉树的每个节点由节点值,左子树和右子树组成。空子树将具有值nil(或一些其他适当选择的原子)。树的常见表示类似于btree(X-Y, LeftSubTree, RightSubTree)(术语X-Y是树的顶部节点的值,在这个问题中,它将是所讨论的部分的尺寸) 。使用这种方案,最小的一块糖果就是btree(1-1, nil, nil)2 x 1糖果栏的一组中断点为btree(2-1, btree(1-1, nil, nil), btree(1-1, nil, nil))

您可以使用CLPFD库约束C #= A + BA #> 0B #> 0,以及消除对称情况A #=< B

答案 2 :(得分:0)

作为一种算法(我不熟悉Prolog),我无法在休息次数中找到任何不同的答案。我尝试了4x4,并且无法提出15以外的答案(上面或下面);我尝试使用5x2并且无法提出除9之外的答案。

在此基础上,我建议使用最简单的编码方法:

while there is more than one column:
    snap off the left-most column
    while this column has more than one square:
         snap off the top square
while the remaining column has more than one square:
    snap off the top square

根据具体情况,您可能希望更改以下一项或多项:(左,列)&lt; - &gt;(顶部,行),left-&gt; right,top-&gt; bottom。