八皇后问题(python)

问题描述

有一个 8x8 的棋盘,往里放 8 个棋子,每个棋子所在的行、列、对角线都不能有另一个棋子。如下,第一幅图是满足条件的一种方法,第二幅图是不满足条件的。
八皇后问题就是期望找到所有符合条件的情况.

将摆法抽象为数据结构

很显然,满足条件的摆法一定是每行有一个棋子. 我们可以定义一个列表,列表的索引代表行号(从 0 开始),值代表摆放的列位置(从 0 开始).

例如可以用列表[0,1,2,3,4,5,6,7]代表下面这种情况:

O * * * * * * *
* O * * * * * *
* * O * * * * *
* * * O * * * *
* * * * O * * *
* * * * * O * *
* * * * * * O *
* * * * * * * O

需要输出的时候我们只需要把该结构还原即可:

def print_queens(result):
    print('='*10)
    for i in result:
        print("* "*i,end="")
        if(i>=0):
            print("O ",end="")
        print("* "*(len(result) - i - 1))

如何判断一个棋子是否符合要求

我们的思路是,从上到下逐行摆放棋子,没摆放一个棋子后检查是否符合要求.

那么不符合的情况一共有三种:

  1. 该棋子正上方已经有棋子存在;
  2. 该棋子左上对角线已经有棋子存在;
  3. 该棋子右上对角线已经有棋子存在;
O * * * * * * *
* * O * * * * *
* * * C * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *

以上情况可以用[0,2,-1,-1,-1,-1,-1,-1]表示,其中-1 表示还未进行该行的考察,我们要考察的行为第 2 行(从 0 开始).

我们将待考察行的索引记为 cur_index,待考察值为 value,三种情况分别可转换为列表的判断:

  1. 该棋子正上方已经有棋子存在;

    • 该值在列表中已存在,例如[0,2,2,-1,-1,-1,-1,-1]
  2. 该棋子左上对角线已经有棋子存在;
    • 索引先前推 n 位, 有 value - n = cur_index - n,例如[0,2,3,-1,-1,-1,-1,-1]
  3. 该棋子右上对角线已经有棋子存在;
    • 索引先前推 n 位, 有 value - n = cur_index + n,例如[0,2,1,-1,-1,-1,-1,-1]
res = []

def check(row, column):
    # 逐行向上考察
    for (index, value) in enumerate(result[:row][::-1]):
        # 这三种分别表示在正上方,右上对角线,左上对角线存在棋子
        if value in [column, column + index + 1, column - index - 1]:
            return False
    result[row] = column
    return True

多层 for 循环嵌套考察所有情况

这种代码最好理解,但是写出来估计会疯掉,而且无法扩展为 n 皇后的问题.

def enum_queens_iter():
    length = len(result)
    for r0 in range(length):
        if check(0,r0):
            result[0] = r0
            for r1 in range(length):
                if check(1,r1):
                    result[1] = r1
                    for r2 in range(length):
                        if check(2,r2):
                            result[2] = r2
                            for r3 in range(length):
                                if check(3,r3):
                                    result[3] = r3
                                    for r4 in range(length):
                                        if check(4,r4):
                                            result[4] = r4
                                            for r5 in range(length):
                                                if check(5,r5):
                                                    result[5] = r5
                                                    for r6 in range(length):
                                                        if check(6,r6):
                                                            result[6] = r6
                                                            for r7 in range(length):
                                                                if check(7,r7):
                                                                    result[7] = r7
                                                                    print_queens(result)

转换为递归的形式

从上面的代码中我们可以看到有大量重复的代码,而且重复代码之间是有结构关系的.这种代码一般可以转换为递归的形式.

以下代码中,我们每次只考察待考察部分的第一行,符合要求再考察剩余部分.

result = [-1] * 8
def enum_queens(row_index):
    length = len(result)

    # 考察当前部分的第一行
    for i in range(length):
        if(check(row_index,i)):
            if row_index == length - 1:
                global total_num
                total_num+=1
                print_queens(result)
            # 考察剩余的部分
            enum_queens(row_index+1)

if __name__ == "__main__":
    enum_queens(0)

原文地址:https://www.cnblogs.com/aloe-n/p/12287761.html

时间: 2024-11-09 21:43:41

八皇后问题(python)的相关文章

八皇后问题python实现

八皇后问题是一个以国际象棋为背景的问题:如何能够在 8×8 的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行.纵行或斜线上.八皇后问题可以推广为更一般的n皇后摆放问题:这时棋盘的大小变为n×n,而皇后个数也变成n.当且仅当 n = 1 或 n ≥ 4 时问题有解. 具体可以参考:https://github.com/chenqiangzhishen/Python/blob/master/pythonAlgorithms/eig

Python学习二(生成器和八皇后算法)

看书看到迭代器和生成器了,一般的使用是没什么问题的,不过很多时候并不能用的很习惯 书中例举了经典的八皇后问题,作为一个程序员怎么能够放过做题的机会呢,于是乎先自己来一遍,于是有了下面这个ugly的代码 def table(m, lst): '''绘制m列的棋盘,每行有个皇后旗子''' head = '┌' + '─┬' * (m-1) + '─┐' row = lambda x: '│' + ' │' * x + '╳│' + ' │' * (m - x - 1) trow = '├' + '─

八皇后问题的Python实现和C#实现

看到八皇后问题的解决思路, 感觉很喜欢. 我用C#实现的版本之前贴在了百度百科上(https://baike.baidu.com/item/%E5%85%AB%E7%9A%87%E5%90%8E%E9%97%AE%E9%A2%98#2_7).百度百科已经有Python版本, 且效率比我的高一点儿, 所以决定把我的版本在博客园贴出来.相信我的版本更容易理解. 希望能够对大家有所帮助.上代码: Python: # EightQueens.py def checkConflict(queenList,

八皇后,回溯与递归(Python实现)

八皇后,回溯与递归(Python实现) 八皇后问题是十九世纪著名的数学家高斯1850年提出 .以下为python语言的八皇后代码,摘自<Python基础教程>,代码相对于其他语言,来得短小且一次性可以打印出92种结果.同时可以扩展为九皇后,十皇后问题. 问题:在一个8*8棋盘上,每一行放置一个皇后旗子,且它们不冲突.冲突定义:同一列不能有两个皇后,每一个对角线也不能有两个皇后.当然,三个皇后也是不行的,四个也是不行的,凭你的智商应该可以理解吧. 解决方案:回溯与递归. 介绍: 1.回溯法 回溯

八皇后问题——回溯法(python&amp;&amp;JAVA)

八皇后问题,是一个古老而著名的问题,问题如下: 在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同一列或同一斜线上,问有多少种摆法. 上边是一个8*8的国际棋盘,可以看到棋盘中的每个格子都标有数字.每个数字都是两位,十位数字表示该格子所在的行,而个位数字表示该格子所在的列. 这样不难发现,处在同一行的两个格子其十位数都相同,处在同一列的两个格子其个位数都相同,处在同一斜线的两个格子有:|两个数字个位数的差|=|两个数字十位数的差|. 主要的三个限制条件明白了

python解决八皇后问题

经典回溯算法:八皇后问题 算法要求: 在国际象棋棋盘上(8*8)放置八个皇后,使得任意两个皇后之间不能在同一行,同一列,也不能位于同于对角线上. 国际象棋的棋盘如下图所示: 问共有多少种不同的方法,并且指出各种不同的放法. # -*- coding:utf-8 -*- __author__ = "tyomcat" print("******八皇后问题的解决方法******") def next_col(current, n=8): length = len(curr

【Python】生成器、回溯和八皇后问题

八皇后问题: 把N个皇后,放在N*N的棋盘上面,从第一行往下放,每个皇后占一行,同时,每个皇后不能处在同一列,对角线上,有多少种放置方法. 思路: 典型的回溯问题: 1.当要放置最后一个皇后时候,默认前N-1个皇后已经全部放置好了,那么验证在第N行上的每个位置是否可行,即是否与之前的皇后在同一列或者对角线即可: 2.如果放置的不是最后一个皇后,则回溯.回溯至刚开始放第一个元素时候,然后不断的返回上一层.每一层都认为下一层传递给自己的是正确的信息 1 def isconflict(state, n

Python----递归------Eight Queens 八皇后问题

递归思想是算法编程中的重要思想. 作为初学者,对递归编程表示很蒙逼,每次遇到需要递归的问题,心里就有一万头草泥马飞过~~~~~~(此处略去一万头草泥马) 在B站看数据结构与算法的视频时,视频中给了两个非常典型的例子--<汉诺塔>和<八皇后问题>,就希望自己用Python实现一下这两个递归程序,其中汉诺塔问题比较简单,还是能够理解,这里就不讲了. <八皇后问题>:说要在一个棋盘上放置8个皇后,但是不能发生战争,皇后们都小心眼,都爱争风吃醋,如果有人和自己在一条线上(水平.

八皇后,回溯与递归

python语句的八皇后代码,摘自<Python基础教程>,代码相对于其他语言,来得短小且一次性可以打印出92种结果.同时可以扩展为九皇后,十皇后问题. 问题:在一个8*8棋盘上,每一行放置一个皇后旗子,且它们不冲突.冲突定义:同一列不能有两个皇后,每一个对角线也不能有两个皇后.当然,三个皇后也是不行的,四个也是不行的,应该凭智商应该可以理解吧. 解决方案:回溯法和递归法 1 import random 2 3 def conflict(state,col): 4 row=len(state)