haskell 基础题解(59)

八皇后问题

【题目】国际象棋的棋盘是 8 x 8 的格子。皇后的威力最大,她可以横向,竖向,对角线方向攻击任意距离的其它棋子。
现在要把8个皇后放在棋盘上,使她们不要互相攻击,有多少种放摆放的方法?

分析: 为了不互相攻击,显然每一行必须且只能放一个皇后。并且每一行的皇后在竖直的位置都不能相同。
可以用一个数组来表达最后的解,比如:[5,3,6,0,2,4,1,7]
就表示,第一行的皇后放在第5格,第二行皇后放在第3格,…
注意,是从第 0 格算起的。

所有可能的解,显然就是: [0…7] 的全排列。
然后筛选出对角线方向互相不攻击的即可。

import Data.List (permutations)

queen :: [[Int]]
queen = filter f (permutations [0..7])
    where
        f [] = True
        f (x:xs) = f xs  && g 1 x xs
        g _ _ [] = True
        g n x (y:ys) = abs (x-y) /= n && g (n+1) x ys

main :: IO ()
main = do
    print $ head queen
    print $ length queen

代码很短,核心逻辑是判断对角线是否相互攻击。

对角线攻击的充分必要条件是:两个子的水平距离等于垂直距离。

92种放法中,很多都是重复的。通过对一种解法进行旋转、镜像变换就可以得到8种方法。
如何去掉这些重复呢?

我们需要一个函数,给定一个局面,可以返回所有的同像局面

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值