1213:八皇后问题
时间限制: 1000 ms 内存限制: 65536 KB提交数: 5367 通过数: 1856【题目描述】
在国际象棋棋盘上放置八个皇后,要求每两个皇后之间不能直接吃掉对方。
【输入】
(无)
【输出】
按给定顺序和格式输出所有八皇后问题的解(见样例)。
【输入样例】
(无)
【输出样例】
No. 11 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 No. 21 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 ...以下省略 例题不怎么详的解: 简介: 八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出: 在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。高斯认为有76种方案。 1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。计算机发明后,有多种计算机语言可以解决此问题。 国际象棋中,皇后可以横斜直三个方向走,步数不受限制,是最强的棋子。 放在本题中考虑,粗略分析,在8*8的棋盘中,要放下八个皇后,每个皇后一定异行异列,才能满足题目要求。 经过以上分析,很明显,每两个皇后之间的位置关系是(用i表示行,j表示列): ai≠bi,aj≠bj(不同行列),|ai-bi|≠|aj-bj|,|ai+bi|≠|aj+bj|(不同斜线); 即不同行不同列不同斜线。 好的,基本思路很简单,接下来是算法实现。别看思路简单,其实这是一道经典的难题。
算法分析: 这是一个有点dp的搜索算法。呃。。。回溯算法。 初步思路是设置一个int型一维数组储存皇后的位置; 接下来,就是完成搜索函数的功能了。 逐行放置棋子,同时检查是否符合两棋子之间的条件关系,直到放完8个棋子。 但是我们如何判断两个皇后之间的关系呢?这里是本题的关键。 这里有一种便捷的方法,因为根据算法每个棋子必定异行,那就设置3个数组,表达某处被占地整列,整左斜线,整右斜线上的格子不得放置下一枚棋子。 为方便起见,我们设置一个关键二维数组vis[3][(此处应大于16,因为最值为i+j=16)]. 首先检查当前列,行,斜线上能否放置:
if(vis[0][i]==0&&vis[1][step+i]==0&&vis[2][step-i+8]==0)//注意:vis[2]由于数组会越界,在行列值相减后必须加至大于0;
如果是,放置棋子,并声明棋子所在行,列,斜线全部无法放置棋子:
vis[0][i]=1;vis[1][i+step]=1;vis[2][step-i+8]=1; a[step]=i;
接下来,搜索下一颗棋子:
dfs(step+1);
完事了以后要销毁证据/滑稽(回溯):
vis[0][i]=0;vis[1][i+step]=0;vis[2][step-i+8]=0;
肥肠好,到这里搜索部分就基本完成了。
加入递归边界:
if(step==9) { tot++; for(int i=1;i<=8;i++) ans[tot][i]=a[i];//设置传值数组,将所有临时数据传入此数组。 return; }
大功告成!
说实话挺简单的,但是我怎么写都是错的,最后还是去看了一眼答案。。。虽说思路一样吧。。。但是为什么我就是错了(蓝瘦)???
没什么需要具体分析的。
样例代码:
#include#include #include #include #define N 100using namespace std;int ans[N][N],a[N];int vis[N][N];int tot;void dfs(int step){ if(step==8+1) { tot++; for(int i=1;i<=8;i++) ans[tot][i]=a[i]; return; } for(int i=1;i<=8;i++) { if(vis[0][i]==0&&vis[1][step+i]==0&&vis[2][step-i+8]==0) { vis[0][i]=1; vis[1][i+step]=1; vis[2][step-i+8]=1; a[step]=i; dfs(step+1); vis[0][i]=0; vis[1][i+step]=0; vis[2][step-i+8]=0; } }}int main(){ dfs(1); for(int t=1;t<=tot;t++) { printf("No. %d\n",t); for(int i=1;i<=8;i++) { for(int j=1;j<=8;j++) { if(ans[t][j]==i) cout<<"1 "; else cout<<"0 "; } cout<
2019-02-05 20:59:02