博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
POJ-2698-八皇后问题
阅读量:6958 次
发布时间:2019-06-27

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

一、题目

2698:八皇后问题

原题链接:http://poj.grids.cn/practice/2698/

时间限制: 
10000ms
内存限制: 
65536kB
描述
在国际象棋棋盘上放置八个皇后,要求每两个皇后之间不能直接吃掉对方。
输入
无输入。
输出
按给定顺序和格式输出所有八皇后问题的解(见Sample Output)。
样例输入
 
样例输出
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 No. 31 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 No. 41 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 No. 50 0 0 0 0 1 0 0 1 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 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 No. 60 0 0 1 0 0 0 0 1 0 0 0 0 0 0 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 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 No. 70 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 No. 80 0 1 0 0 0 0 0 1 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 No. 90 0 0 0 1 0 0 0 1 0 0 0 0 0 0 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 0 0 1 0 0 0 1 0 0 0 0 0 ...以下省略
提示     此题可使用函数递归调用的方法求解。

二、分析

   
1、递归法;2、交表法
八皇后问题经典解析:

八皇后问题,是一个古老而著名的问题,是回溯算法的典型例题。该问题是十九世纪著名的数学家高斯1850年提出:在8X8格的国际象棋上摆放八个皇后,使 其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。计算机发明后,有多种方法可 以解决此问题。

摘自百度百科

解题思路:深度搜索加记忆数组
*因为皇后不能处于同一行,同一列,同一斜线(即主对角线和副对角线),所以可以判断出8个皇后分别各占一行
*不妨假设从第一行开始,行数依次加一确定每一行皇后的位置,在下面的程序中cur代表行号,因为我们依次让
*行号加一,所以不会存在行号重叠的现象,接下来只需判断列数和对角线没有发生重叠即可,这里,我们用一个记
*忆状态的数组(vis[][])来存储列和对角线的状态,每次确定一个皇后的位置,首先判断其对应的列和对角线是否
*染色,如果没有染色,则该位置有效,并染色,这样就不会出现列和对角线重叠的问题.
下面重点讲解一下对角线,其原理可用下图说明:
 (格子(i-j)的值标示了主对角线)
同理读者自行可以推出
 (格子(i+j)的值标示了副对角线)
又因为主对角线的值有为负数的情况,所以我们在标记的时候应该加>=7的数,所有值都加了>=7所以标记的效果并没有改变

简化版代码:
1 #include
2 using namespace std; 3 bool vis[3][30];//记忆数组判断列,主对角线,副对角线是否被占 4 int ans=0; 5 void dfs(int cur) 6 {
7 if(cur==9)//如果当前行数超过8(表明八个皇后已经放好)则结果加一,返回继续递归 8 {
9 ans++; 10 return ; 11 } 12 //vis[0][i]判断列,vis[i][cur-i+8]判断主对角线,vis[2][cur+i]判断副对角线 13 for(int i=1;i<=8;i++)if(!vis[0][i]&&!vis[1][cur-i+8]&&!vis[2][cur+i]) 14 {
15 vis[0][i]=vis[1][cur-i+8]=vis[2][cur+i]=true; 16 dfs(cur+1);//深度搜索 17 vis[0][i]=vis[1][cur-i+8]=vis[2][cur+i]=false; 18 } 19 } 20 int main() 21 {
22 dfs(1);//初始化cur为1,即从第一行开始 23 cout<<"有 "<
<<" 种结果."<
三、AC源代码
1、递归求解
1 #include
2 using namespace std; 3 4 bool vis[3][20];//记忆数组判断列,主对角线,副对角线是否被占 5 int ans=0,num=1; 6 int p=0,pos[8]; 7 8 void dfs(int cur); 9 void print(); 10 11 int main() 12 {
13 dfs(1);//初始化cur为0,即从第一行开始 14 return 0; 15 } 16 17 void dfs(int cur) 18 {
19 if(cur>8)//如果当前行数超过8(表明八个皇后已经放好)则结果加一,返回继续递归 20 {
21 ans++; 22 print(); 23 return; 24 } 25 //vis[0][i]判断列,vis[i][cur-i+8]判断主对角线,vis[2][cur+i]判断副对角线 26 for(int i=1;i<=8;i++) 27 if(!vis[0][i]&&!vis[1][cur-i+8]&&!vis[2][cur+i]) 28 {
29 pos[p++]=i; 30 vis[0][i]=vis[1][cur-i+8]=vis[2][cur+i]=true; 31 dfs(cur+1);//深度搜索 32 vis[0][i]=vis[1][cur-i+8]=vis[2][cur+i]=false; 33 p--; 34 } 35 } 36 37 void print() 38 {
39 int i,j; 40 cout<<"No. "<
<
2、直接交表
1 #include 
2 int pos[736]={
1,5,8,6,3,7,2,4,1,6,8,3,7,4,2,5,1,7,4,6,8,2,5,3,1,7,5,8,2,4,6,3,2,4,6,8,3,1,7,5,2,5,7,1,3,8,6,4,2,5,7,4,1,8,6,3,2,6,1,7,4,8,3,5,2,6,8,3,1,4,7,5,2,7,3,6,8,5,1,4,2,7,5,8,1,4,6,3,2,8,6,1,3,5,7,4,3,1,7,5,8,2,4,6,3,5,2,8,1,7,4,6,3,5,2,8,6,4,7,1,3,5,7,1,4,2,8,6,3,5,8,4,1,7,2,6,3,6,2,5,8,1,7,4,3,6,2,7,1,4,8,5,3,6,2,7,5,1,8,4,3,6,4,1,8,5,7,2,3,6,4,2,8,5,7,1,3,6,8,1,4,7,5,2,3,6,8,1,5,7,2,4,3,6,8,2,4,1,7,5,3,7,2,8,5,1,4,6,3,7,2,8,6,4,1,5,3,8,4,7,1,6,2,5,4,1,5,8,2,7,3,6,4,1,5,8,6,3,7,2,4,2,5,8,6,1,3,7,4,2,7,3,6,8,1,5,4,2,7,3,6,8,5,1,4,2,7,5,1,8,6,3,4,2,8,5,7,1,3,6,4,2,8,6,1,3,5,7,4,6,1,5,2,8,3,7,4,6,8,2,7,1,3,5,4,6,8,3,1,7,5,2,4,7,1,8,5,2,6,3,4,7,3,8,2,5,1,6,4,7,5,2,6,1,3,8,4,7,5,3,1,6,8,2,4,8,1,3,6,2,7,5,4,8,1,5,7,2,6,3,4,8,5,3,1,7,2,6,5,1,4,6,8,2,7,3,5,1,8,4,2,7,3,6,5,1,8,6,3,7,2,4,5,2,4,6,8,3,1,7,5,2,4,7,3,8,6,1,5,2,6,1,7,4,8,3,5,2,8,1,4,7,3,6,5,3,1,6,8,2,4,7,5,3,1,7,2,8,6,4,5,3,8,4,7,1,6,2,5,7,1,3,8,6,4,2,5,7,1,4,2,8,6,3,5,7,2,4,8,1,3,6,5,7,2,6,3,1,4,8,5,7,2,6,3,1,8,4,5,7,4,1,3,8,6,2,5,8,4,1,3,6,2,7,5,8,4,1,7,2,6,3,6,1,5,2,8,3,7,4,6,2,7,1,3,5,8,4,6,2,7,1,4,8,5,3,6,3,1,7,5,8,2,4,6,3,1,8,4,2,7,5,6,3,1,8,5,2,4,7,6,3,5,7,1,4,2,8,6,3,5,8,1,4,2,7,6,3,7,2,4,8,1,5,6,3,7,2,8,5,1,4,6,3,7,4,1,8,2,5,6,4,1,5,8,2,7,3,6,4,2,8,5,7,1,3,6,4,7,1,3,5,2,8,6,4,7,1,8,2,5,3,6,8,2,4,1,7,5,3,7,1,3,8,6,4,2,5,7,2,4,1,8,5,3,6,7,2,6,3,1,4,8,5,7,3,1,6,8,5,2,4,7,3,8,2,5,1,6,4,7,4,2,5,8,1,3,6,7,4,2,8,6,1,3,5,7,5,3,1,6,8,2,4,8,2,4,1,7,5,3,6,8,2,5,3,1,7,4,6,8,3,1,6,2,5,7,4,8,4,1,3,6,2,7,5}; 3 int main() 4 {
5 int i,j,n=92; 6 while(n--) 7 {
8 printf("No. %d\n",92-n); 9 for(i=0;i<8;i++) 10 {
11 for(j=0;j<8;j++) 12 if(i==pos[(91-n)*8+j]-1) 13 printf("1 "); 14 else 15 printf("0 "); 16 printf("\n"); 17 } 18 } 19 return 0; 20 }

转载于:https://www.cnblogs.com/deadacm/archive/2011/12/18/2291915.html

你可能感兴趣的文章
CIO们从云中学到的那些经验教训
查看>>
混合云和多云管理不再难:基础架构即代码来帮忙
查看>>
大数据能否解决城市所面临的环境问题
查看>>
数据库安全需要遵循的8项最佳实践
查看>>
关于HTTP推送的一些问题
查看>>
Spring IoC 学习(2)
查看>>
综合布线系统的设计分析
查看>>
论金融机构采用CDP容灾备份的意义
查看>>
Java性能调优工程的几点建议
查看>>
DI的力量,2017 UBDC全域大数据峰会即将开启
查看>>
数据中心的那些未来技术
查看>>
如何善用产品设计的三个层级
查看>>
如何在Amazon AWS上设置一台Linux服务器
查看>>
网站优化遇到死链怎么合理的处理?
查看>>
全球智慧城市进入快速发展阶段
查看>>
AI 黑客会大规模进军网络安全领域吗?为时尚早,因为太贵了
查看>>
科通芯城康敬伟:不照抄别人美国也没这模式
查看>>
每个平安城市的背后,都需要一个默默付出的“她”!
查看>>
外资赴中国设厂加剧竞争,中国晶圆代工厂今年全力冲刺 28 纳米制程
查看>>
《Servlet和JSP学习指南》一1.10 处理HTML表单
查看>>