Python用迭代(yield)和递归解决八皇后问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python用迭代(yield)和递归解决八皇后问题相关的知识,希望对你有一定的参考价值。
参考技术A 国际象棋的皇后行走具有最高的灵活性,可以横、竖、斜共八个方向无限步行走。你需要将国际象棋8个皇后放在棋盘上,条件是任何一个皇后都不能威胁其他皇后,即任何两个皇后都不能吃掉对方。
分析:在棋盘的第一行尝试为第一个皇后选择一个位置,再在第二行尝试为第二个皇后选择一个位置,依次类推。在发现无法为一个皇后选择合适的位置后,回溯到前一个皇后,并尝试为它选择另一个位置。当八个皇后都放在棋盘上时即得到一种解。
用元组(其他序列也可以)表示可能的解(或一部分),例如(1,3,5)表示当前共摆放了三个皇后,第一个皇后在1行1列,第二个皇后在2行3列,第三个皇后在3行5列。
当前状态state,下一个皇后在下一行的next_x位置,根据皇后的行走规则,如果已有的皇后可以吃掉下一个皇后,则表示有冲突,否则没有。
函数conflict定义:接受用状态元组表示的既有皇后的位置,并确定下一个皇后的位置是否会导致冲突。
参数 next_x 表示下一个皇后的水平位置(x 坐标,即列),而 next_y 为下一个皇后的垂直位置(y 坐标,即行)。这个函数对既有的每个皇后执行简单的检查:如果下一个皇后与当前皇后的 x 坐标相同或在同一条对角线上,将发生冲突,因此返回True ;如果没有发生冲突,就返回False 。
abs(state[i] - next_x) in (0, next_y - i) 表示两个皇后的水平距离为0或等于垂直距离时为真、否则为假。
算法入门经典-第七章 例题7-2 八皇后问题
原本利用回溯思想解决的经典八皇后问题,其实也是可以用递归解决的~
八皇后的递归解决思路:
从第一行开始,依次判断0~8列的哪一列可以放置Queen,这样就确定了该行的Queen的位置,然后行数递增,继而递归实现下一行的判断,依次类推直到行数增加到8(行数从0开始的),此时为递归-----归的条件,即表示一种八皇后的解决方法完成,打印结果;之后进行下一种解决方法的寻找,大致思路个人理解是这样
noDanger(row,j,(*chess)[8])函数是判断第row行第j列是否可以放置Queen
#include<stdio.h> int count=0; //参数row:起始行 //参数n:表示列数 //参数(*chess)[8]表示指向棋盘每一行的指针 int NotDanger(int row,int j,int (*chess)[8])//比较不同行同列上是否有其他皇后 { int i,k,flag1=0,flag2=0,flag3=0,flag4=0,flag5=0; //判断列方向 for(i=0;i<8;i++) { if(*(*(chess+i)+j)!=0) //在这之前列上有其他皇后 { flag1=1; break; } } for(i=row,k=j;i>=0&&k>=0;i--,k--) { if(*(*(chess+i)+k)!=0) //左上方 { flag2=1; break; } } for(i=row,k=j;i<8&&k<8;i++,k++) { if(*(*(chess+i)+k)!=0) //右下方 { flag3=1; break; } } for(i=row,k=j;i>=0&&k<8;i--,k++) { if(*(*(chess+i)+k)!=0) //右上方 { flag4=1; break; } } for(i=row,k=j;i<8&&k>=0;i++,k--) { if(*(*(chess+i)+k)!=0) //左下方 { flag5=1; break; } } if(flag1||flag2||flag3||flag4||flag5) { return 0;//如果有一个位置被占 有危险 } else return 1; } /* int noDanger(int row,int j,int (*chess)[8]) { int flag1=0,flag2=0,flag3=0,flag4=0,flag5=0; int i,k; //判断列 for(i=0;i<8;i++) { if(*(*(chess+i)+j)!=0) { flag1=1; break; } } //判断左上方 for(i=row,k=j;i>=0&&k>=0;i--,k--) { if(*(*(chess+i)+k)!=0) { flag2=1; break; } } //判断右下方 for(i=row,k=j;i<8&&k<8;i++,k++) { if(*(*(chess+i)+k)!=0) { flag3=1; break; } } //判断左下方 for(i=row,k=j;i<8&&k>=0;k--,i++) { if(*(*(chess+i)+k)!=0) { flag4=1; break; } } //判断右上方 for(i=row,k=j;i>=0&&k<8;k++,i--) { if(*(*(chess+i)+k)!=0) { flag5=1; break; } } if(flag1||flag2||flag3||flag4||flag5) { return 0; }else { return 1; } } */ EightQueen(int row,int n,int (*chess)[8]) { int chess2[8][8]; int i,j; for(i=0;i<8;i++) { for(j=0;j<8;j++) { chess2[i][j]=chess[i][j]; } } if(8==row) { printf("第%d 种\n",count+1); for(i=0;i<8;i++) { for(j=0;j<8;j++) printf("%3d ",*(*(chess2+i)+j)); printf("\n"); } count++; } else{ //判断这个位置是否危险 j<列 for(j=0;j<n;j++) { if(NotDanger(row,j,chess2))//尝试每一列是否危险 { for(i=0;i<8;i++) { //整行所有列的位置赋值为0 *(*(chess2+row)+i)= 0; } *(*(chess2+row)+j)=1;//皇后的位置赋值为1 EightQueen(row+1,n,chess2);//继续往下一行 递归 } } } } int main() { int chess[8][8],i,j; for(i=0;i<8;i++) { for(j=0;j<8;j++) chess[i][j]=0; } EightQueen(0,8,chess); printf("总共有%d种解决方法",count); return 0; }
以上是关于Python用迭代(yield)和递归解决八皇后问题的主要内容,如果未能解决你的问题,请参考以下文章