博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
八皇后问题的解题思路
阅读量:1872 次
发布时间:2019-04-26

本文共 5457 字,大约阅读时间需要 18 分钟。

是回溯递归思想的展现。

回溯法和枚举法的区别

回溯法与穷举法有某些联系,它们都是基于试探的。

穷举法要将一个解的各个部分全部生成后,才检查是否满足条件,若不满足,则直接放弃该完整解,然后再尝试另一个可能的完整解,它并没有沿着一个可能的完整解的各个部分逐步回退生成解的过程。
而对于回溯法,一个解的各个部分是逐步生成的,当发现当前生成的某部分不满足约束条件时,就放弃该步所做的工作,退到上一步进行新的尝试,而不是放弃整个解重来。

实现1:百度百科八皇后问题里面的python实现

def queen(A, cur=0):    global num    if cur == len(A):        print(A)  # 打印解,每个位置对应的列        num += 1        return 0    for col in range(len(A)):        A[cur], flag = col, True        for row in range(cur):            # 如果检测出前面的行和当前行是同列的,或者在当前点的等腰直角三角形上            if A[row] == col or abs(col - A[row]) == cur - row:                flag = False                break        if flag:  # 如果当前点合适的话那就下一个点,如果当前点不合适的话那就当前点往右再走一步            queen(A, cur+1)num = 0queen([None]*8)print(num)

暴力解法盲目的枚举算法:通过8重循环模拟搜索空间中的8个状态,从中找出满足约束条件的“答案状态”。下面的算法总共需要8^8=2^24

优点:程序思想比较简单

缺点:问题转化为“从64个格子中选一个子集”,使得“子集中恰好有8个格子,且任意选出两个格子都不在同一行,同一列或者同意对角线上”。这恰好是子集枚举问题。然而,64个格子的子集有2^64个,太大了,则并不是一个很好的模型。

def queens():    a=[None]*8    count=0    for i0 in range(8):        a[0]=i0        for i1 in range(8):            a[1]=i1            for i2 in range(8):                a[2]=i2                for i3 in range(8):                    a[3]=i3                    for i4 in range(8):                        a[4]=i4                        for i5 in range(8):                            a[5]=i5                            for i6 in range(8):                                a[6]=i6                                for i7 in range(8):                                    a[7]=i7                                    if check(a):                                        count +=1                                        # print(' '.join(map(str,a)))    return countdef check(a):    n=len(a)    for i in range(1,n):        for j in range(i):            if a[i]==a[j] or abs(a[i]-a[j])==i-j:                return False    return True                    count=queens()print(count)

考虑到其中的限制条件,不能同行同列,那么第一行8个位置,第二行7个位置,第三行6个位置,这样算法总共只需要8!=40320

枚举的次数不会超过这个值。当前判断如果走不通就掉头,缺点也是一样的,对于n未知的情况或者n非常大的情况,写法是不好的(需要n个for循环)

def queens():    a=[None]*8    count=0    for i0 in range(8):        a[0]=i0        for i1 in range(8):            a[1]=i1            if check(a,1):                continue            for i2 in range(8):                a[2]=i2                if check(a,2):                    continue                for i3 in range(8):                    a[3]=i3                    if check(a,3):                        continue                    for i4 in range(8):                        a[4]=i4                        if check(a,4):                            continue                        for i5 in range(8):                            a[5]=i5                            if check(a,5):                                continue                            for i6 in range(8):                                a[6]=i6                                if check(a,6):                                    continue                                for i7 in range(8):                                    a[7]=i7                                    if check(a,7):                                        continue                                    else:                                        count +=1                                        # print(' '.join(map(str,a)))    return countdef check(a,n):    for i in range(n):        if a[i]==a[n] or abs(a[n]-a[i])==n-i:                return False    return True                    count=queens()print(count)

上述,它只针对八皇后问题,解决任意的n皇后问题还要修改程序结构。如果要解决n皇后的问题,就需要将n作为参数传递给函数,函数需要重写来实现回溯(不能采用级联的for循环,n不确定);从另一方面,程序中出现了大量的for循环,而且for中的函数结构很相似,自然想到的是递归迭代回溯。这就是回溯比较常用的两种实现方法:非递归回溯和递归回溯。

递归回溯法:

def queens(A,k=0):    global count    if k==len(A):        print(A)        count +=1        return 0    for i in range(len(A)):        A[k]=i        if not check(A,k):            continue        else:            queens(A,k+1)def check(a,n):    for i in range(n):        if a[i]==a[n] or abs(a[n]-a[i])==n-i:                return False    return True                    count =0queens([None]*8,k=0)print(count)

非递归方法:比较复杂,暂时还没有转化成python,下面只给出C++语言的实现

void backdate (int n){      int count = 0;    int a[100];    int k = 1;    a[1]=0;       while(k>0)    {        a[k]=a[k]+1;//对应for循环的1~n        while((a[k]<=n)&&(!check_2(a,k)))//搜索第k个皇后位置        {            a[k]=a[k]+1;        }                  if(a[k]<=n)//找到了合理的位置        {            if(k==n )            {//找到一组解                for(int i=1;i<=8;i++)                  {                    cout<

下面的一道题

描述

会下国际象棋的人都很清楚:皇后可以在横、竖、斜线上不限步数地吃掉其他棋子。如何将8个皇后放在棋盘上(有8 * 8个方格),使它们谁也不能被吃掉!这就是著名的八皇后问题。

对于某个满足要求的8皇后的摆放方法,定义一个皇后串a与之对应,即a=b1b2...b8,其中bi为相应摆法中第i行皇后所处的列数。已经知道8皇后问题一共有92组解(即92个不同的皇后串)。
给出一个数b,要求输出第b个串。串的比较是这样的:皇后串x置于皇后串y之前,当且仅当将x视为整数时比y小。

输入

第1行是测试数据的组数n,后面跟着n行输入。每组测试数据占1行,包括一个正整数b(1 <= b <= 92)

输出

输出有n行,每行输出对应一个输入。输出应是一个正整数,是对应于b的皇后串。

样例输入

2192

样例输出

1586372484136275
# 给n皇后问题的所有解进行排序,按从小到大的顺序:例如,其中三组解[6 4 2 0 5 7 1 3],[6 1 5 2 0 3 7 4],[7 2 0 5 1 4 6 3];# 排序后是[6 1 5 2 0 3 7 4],[6 4 2 0 5 7 1 3],[7 2 0 5 1 4 6 3]# 从上面打印可以看出,打印的顺序就是从小打到的顺序。def queens(A,k=0):    global count,seek    if k==len(A):        # print(A)        count +=1        if count==seek:            print(A)        return 0    for i in range(len(A)):        A[k]=i        if check(A,k):            queens(A,k+1)           def check(a,n):    for i in range(n):        if a[i]==a[n] or abs(a[n]-a[i])==n-i:                return False    return True                    count,seek =0,1queens([None]*8,0)print(count)

 

 

 

 

 

 

 

 

 

 

 

转载地址:http://ecwbf.baihongyu.com/

你可能感兴趣的文章
电赛 | 19年全国一等奖,北航学子回忆录(下)
查看>>
突破!台积电1nm芯片,有了新进展。
查看>>
一文读懂全系列树莓派!
查看>>
自制一个害羞的口罩,见人就闭嘴,戴着可以喝奶茶
查看>>
聊聊我是如何编程入门的
查看>>
J-Link该如何升级固件?
查看>>
485通信自动收发电路,历史上最详细的解释
查看>>
一位头发发白的神人教你怎么写程序,运维,买电脑,写文章,平面设计!
查看>>
「第三篇」全国电子设计竞赛,这些你必须知道的比赛细节,文末附上近十年电赛题目下载...
查看>>
5G小科普(漫画版,So easy!)
查看>>
「第四篇」电赛控制题可以准备一些什么?
查看>>
「第六篇」对于电赛,我们应该看重什么?
查看>>
树莓派翻车了
查看>>
这位电子工程师,你不能错过。
查看>>
「重磅猜题之第二篇」2019年大学生电子设计竞赛
查看>>
干货分享 JVM 之第 3 篇 —— Java 内存结构相关
查看>>
基于 Hystrix 高并发服务限流第 2 篇 —— 服务隔离(线程池隔离、信号量隔离)
查看>>
SpringBoot 整合 JWT 实现统一认证
查看>>
TypeError: this.getOptions is not a function
查看>>
el-table 二维数组合并行
查看>>