2n皇后问题(经典8皇后问题)

8皇后问题是回溯算法的经典案例,回溯又称深搜,简单来说就是递归的枚举。
回溯算法优于穷举在于一旦遇到达不到目标或不优,立即向上返回重新选择,寻找别的路径。
有点像暴力破解,不过一旦不达目标则不继续当前方案,因此是比暴力破解省下减少很多运算量

问题描述
  给定一个n*n的棋盘,棋盘中有一些位置不能放皇后。现在要向棋盘中放入n个黑皇后和n个白皇后,使任意的两个黑皇后都不在同一行、同一列或同一条对角线上,任意的两个白皇后都不在同一行、同一列或同一条对角线上。问总共有多少种放法?n小于等于8。
输入格式
  输入的第一行为一个整数n,表示棋盘的大小。
  接下来n行,每行n个0或1的整数,如果一个整数为1,表示对应的位置可以放皇后,如果一个整数为0,表示对应的位置不可以放皇后。
输出格式
  输出一个整数,表示总共有多少种放法。
样例输入
4
1 1 1 1
1 1 1 1
1 1 1 1``
1 1 1 1
样例输出
2
具体实现参考别人的方案加了一点内容,过程如下:

while True:
    try:  # 先放白皇后,再放黑皇后
        n = int(input())  # n是一开始的黑白皇后的个数
        s = []  # 存放原始的0,1位置
        result = []
        temp_W = [None for x in range(n)]  # 临时存放白皇后
        temp_B = [None for x in range(n)]  # 临时存放黑皇后
        for i in range(n):
            s.append(input().split())  # 输入0,1位置
        def valid_W(temp_W, row):  # 判断当前位置放白皇后是否合法
            if s[row][temp_W[row]] == "1":
                for i in range(row):
                    # 下面这个判断条件是:判断对角线,判断是否是白皇后自己的列
                    if abs(temp_W[i] - temp_W[row]) == abs(i - row) or temp_W[i] == temp_W[row]:
                        return False
                return True

        def valid_B(temp_B,row,temp_W):  # 判断当前位置放黑皇后是否合法
            if s[row][temp_B[row]] == '1' and temp_B[row] != temp_W[row]:  # 判断这个位置能否放皇后
                for i in range(row):
                    # 判断是否对角线,是否是自己的列,判断这个位置有没有先放白皇后
                    if abs(temp_B[i] - temp_B[row]) == abs(i-row) or temp_B[i] == temp_B[row]:
                        return False
                return True

        def dfs_W(temp_W,row):  # temp记录当前所有合法的皇后的位置,row是继续往下一行里面放皇后
            if row == n:  # 当前进行到n,表示找到了白皇后的一种排列方式,跳出递归
                dfs_B(temp_B,0)  # 白皇后排好之后跳到排列黑皇后
            else:
                for col in range(n):  # col是列,就是要遍历这一行的所有列,判断在某个位置上是否合法
                    temp_W[row] = col
                    if valid_W(temp_W,row):
                        dfs_W(temp_W,row+1)

        def dfs_B(temp_B,row):  # temp记录当前所以合法皇后的位置,row是继续往下一行里面放皇后
            if row == n:  # 当前进行到n,表示找到了n皇后的一种排列方式,跳出递归
                result.append(temp_B[:])  # 将找到的黑皇后排列方式存储到result里面
                return
            else:
                for col in range(n):  # col是列,遍历这一行所有列,判断在某位置是否合法
                    temp_B[row] = col
                    if valid_B(temp_B,row,temp_W):
                        dfs_B(temp_B,row+1)

        dfs_W(temp_W,0)
        print(len(result))
    except:
        break  # 通过异常输入跳出循环(如不输入直接运行)

猜你喜欢

转载自blog.csdn.net/qq_45701131/article/details/105718746