我作为一个作业被赋予了使用prolog编写的解决方案 战舰单人拼图。对于那些不熟悉的人来说,这个谜题是有效 一个6乘6的网格,根据提供的方式放置一系列船只 每个行和列的约束,即第一行必须包含3个带有船的方格,第二行必须包含1个带有船的方格,第三行必须包含0个方格等其他行和列。
每个谜题都带有它自己的一组约束和显示的方块,通常是两个。这里可以看到一个例子: battleships
所以,这就是我所做的:
step([ShipCount,Rows,Cols,Tiles],[ShipCount2,Rows2,Cols2,Tiles2]):-
ShipCount2 is ShipCount+1,
nth1(X,Cols,X1),
X1\==0,
nth1(Y,Rows,Y1),
Y1\==0,
not(member([X,Y,_],Tiles)),
pairs(Tiles,TilesXY),
notdiaglist(X,Y,TilesXY),
member(T,[1,2,3,4,5,6]),
append([X,Y],[T],Tile),
append([Tile],Tiles,Tiles2),
dec_elem1(X,Cols,Cols2),dec_elem1(Y,Rows,Rows2).
dec_elem1(1,[A|Tail],[B|Tail]):- B is A-1.
dec_elem1(Count,[A|Tail],[A|Tail2]):- Count1 is Count-1,dec_elem1(Count1,Tail,Tail2).
neib(X1,Y1,X2,Y2) :- X2 is X1,(Y2 is Y1 -1;Y2 is Y1+1; Y2 is Y1).
neib(X1,Y1,X2,Y2) :- X2 is X1-1,(Y2 is Y1 -1;Y2 is Y1+1; Y2 is Y1).
neib(X1,Y1,X2,Y2) :- X2 is X1+1,(Y2 is Y1 -1;Y2 is Y1+1; Y2 is Y1).
notdiag(X1,Y1,X2,Y2) :- not(neib(X1,Y1,X2,Y2)).
notdiag(X1,Y1,X2,Y2) :- neib(X1,Y1,X2,Y2),((X1 == X2,t(Y1,Y2));(Y1 == Y2,t(X1,X2))).
notdiaglist(X1,Y1,[]).
notdiaglist(X1,Y1,[[X2,Y2]|Tail]):-notdiag(X1,Y1,X2,Y2),notdiaglist(X1,Y1,Tail).
t(X1,X2):- X is abs(X1-X2), X==1.
pairs([],[]).
pairs([[X,Y,Z]|Tail],[[X,Y]|Tail2]):-pairs(Tail,Tail2).
我代表一个列表为[Count,Rows,Columns,Tiles]
的州。最后一个状态必须是
[10,[0,0,0,0,0,0],[0,0,0,0,0,0], somelist]
。拼图从初始状态开始,例如
initial([1, [1,3,1,1,1,2] , [0,2,2,0,0,5] , [[4,4,1],[2,1,0]]]).
我尝试以下列方式找到解决方案:
run:-initial(S),step(S,S1),step(S1,S2),....,step(S8,F).
现在,遇到困难:如果我使用member(T,[1])
将自己限制在一种船舶部件
而不是
member(T,[1,2,3,4,5,6])
它工作正常。但是,当我使用T所需的全部可能值时 之后,查询永远不会结束,因为它运行的时间太长了。这让我很困惑,因为:
(b)从单一类型的船舶到6种类型增加了数量 最后一步的选项是6倍,其中 不应该产生如此巨大的影响。
那么,发生了什么?
答案 0 :(得分:1)
直接回答你的问题,正在进行的是Prolog正试图筛选出巨大的可能性空间。
您正确认为更改该行会将 last 调用的搜索空间增加6倍,请注意,例如9个调用的搜索空间大小不是&n #39; t与一次通话大小的9倍成比例。 Prolog将在失败时回溯,因此它与一个呼叫提升到第九次幂的可能结果的大小成比例(实际上是上限)。
这意味着当我们允许T
接受6倍的值时,我们可以预期Prolog需要搜索的空间大小最多增长6 ^ 9 = 10077696。
当然,如果我们以step
开始调用initial
9次,那么解决方案并不存在(如我所知)并不存在帮助。由于最后一次通话将失败,Prolog将继续尝试,直到它最终放弃之前所有可能性(其中有很多可能性)已经用尽。
就解决方案而言,我不确定我对此问题了解得多。如果T的值是适合于网格的船舶类型(例如,单个正方形,2平方船的一半,3平方船的一部分),您应该注意到这比您提供的信息要多得多行/列上的数字。
现在,在伪代码中,您的step
看起来像这样:
我建议你这样做:
通过使用我们首先获得的最具体的信息(在这种情况下,以前放置的部分),我们可以减少Prolog必须做的工作量并使事情合理地快速返回。