八皇后问题的prolog解法(双坐标法)

学习目标:

利用prolog解决八皇后问题

学习内容:

prolog基础


学习产出:

偶然间看到了八皇后问题,和数独类似,前后充满了严密的逻辑性。所以我想到应该可以用prolog语言来解决。查阅资料得知有三种解法。双坐标法、单坐标法、四坐标法。现在先介绍双坐标法。具体八皇后问题和prolog语言是什么。请自行查阅资料。

1.双坐标法。

在这里我们把解的通式写成:[1/Y1,2/Y2,3/Y3,4/Y4,5/Y5,6/Y6,7/Y7,8/Y8].(这里1,2,3,4,5,6,7,8为横坐标,Y为纵坐标,针对的是8*8的问题)。这样具体的解会有很多个。

双坐标法是相对简单的解法。只需满足两个条件:

a.Y在[1,2,3,4,5,6,7,8]中。

b.任意两个皇后不在同一行(列),且不在同一对角线上。不在同一行已经满足了。假如有两个皇后,她们的坐标分别为:(X,Y),(X1,Y1),则不在同一列可表示为Y!=Y1,而不在同一个对角线上可表示为(对角线有上对角线和下对角线):X-X1!=Y-Y1,OR X-X1!=Y1-Y,这里自行画图即可推出(初中知识)。

现在就可以写prolog代码了,代码如下:

member(A,[A|T]).
member(A,[H|B]):-member(A,B).
solution([]).
solution([X/Y|A]):-solution(A),
                    member(Y,[1,2,3,4,5,6,7,8]),
                    notattack(X/Y,A).
notattack[_,[]].
notattack(X/Y,[X1/Y1|R]):-not(Y=Y1),
                           Yd is Y1-Y,Xd1 is X1-X,
                            not(Yd=xd1),
                            Xd2 is X-X1,
                            not(Yd=xd2),
                            notattack(X/Y,R).
template([1/Y1,2/Y2,3/Y3,4/Y4,5/Y5,6/Y6,7/Y7,8/Y8]).

在swi-prolog解释器中输入:template(Q),solution(Q).即可得到所有的解。 

代码解释:

1.        

member(A,[A|T]).
member(A,[H|B]):-member(A,B).

这个是用来判断A是否在列表B中的。算是“轮子”,直接拿来用即可。

2       

solution([]).
solution([X/Y|A]):-solution(A),member(Y,[1,2,3,4,5,6,7,8]),notattack(X/Y,A).

 这里第一句就是边界条件,因为后面用到了递归,所以这是必要的。从最简单的开始,即空列表,这里就认为空列表也算是解。

然后第二句就是对上上面提到的规则的总体概述。个人理解:solution(S),这里的S里面是所有解的一个集合,即S=[[1,2,3,],[4,5,6],[7,8,9],[a,b,c],[d,r,f]]。(这里仅仅是表示格式是这样)。然后再逐个对解进行“约束”。相当于python中的for。但prolog中没有for语句,所以直接用solution([X/Y|Others])来逐一进行匹配。然后solution(A)是递归,没有他不能完成逐一匹配。member就相当于对Y的取值进行限制。notattack即是不能在同一行(列)且不能在同一对角线上。

3.

notattack[_,[]].
notattack(X/Y,[X1/Y1|R]):-not(Y=Y1),
                            Yd is Y1-Y,Xd1 is X1-X,
                            not(Yd=xd1),
                            Xd2 is X-X1,
                            not(Yd=xd2),
                            notattack(X/Y,R).

这里就是对上面中的代码的具体解释。依然首先是确定边界条件。第二步中的solution(X/Y|A),递归完后的最终形式肯定是solution(X/Y|[]),相应的notattack为notattack(X/Y,[]).所以notatack的边界条件就确定了。notattack是对两个坐标进行比较,所以第一个位置填X/Y,后面第二个位置自然是解列表中的坐标了,所以用[X1/Y1|R]来表示解列表中的第一个坐标,后面的语句就是对逻辑的解释了。

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值