八皇后问题解题报告(dfs
2016-02-26 11:29
435 查看
这里是代码传送门
所谓八皇后问题,一开始接触,上学期舍友提及的,但是因为各种原因,水平不够,并没有关心,偶然之间,再次遇见,便进行的尝试(棋盘是0-7的,不是1-8的...开始打弄错了)所谓八皇后问题,就是在8X8的棋盘上,求如何让可以往八个方向直走的皇后不互相攻击的摆放方法的解;
很显然,我的第一想法是用深搜剪枝(书上说是 回朔法 )
如何实现呢?我的想法是,先预定让每个皇后占一行,然后暴力搜索皇后所在列的情况,然后递归剪掉不满足的情况;
代码如下
#include<cstdio> #include<queue> #include<stack> #include<string> #include<cstdlib> #include<cstring> #include<cmath> #include<iomanip> #include<algorithm> #include<iostream> #define PI acos(-1) #define ull unsigned __int64 #define Min(a,b) ((a>b)?b:a) #define Max(a,b) ((a>b)?a:b) #define INF 1000000007 using namespace std; bool v[8]={0};//用来记忆 int node[8];//记录不同行的皇后所在的列 int coun=0;//统计一共解法 void dfs(int t) { if(t==8)//如果能达到8行,说明是满足条件的,不然会被剪枝 { for(int i=0;i<8;i++) printf("(%d,%d) ",i,node[i]); printf("\n"); coun++; return ; } for(int i=0;i<8;i++)//遍历 { if(!v[i])//皇后的列数不能相同 { int flag=true;//判断斜线 for(int j=0;j<t;j++) { if(node[j]==i-(t-j)||node[j]==i+(t-j)) //遍历前面已经给出的皇后是否在同一斜线位置,前面一个是k=-1的斜线,后面是k=1的斜线 { flag=false;//如果在同一斜线,则不能满足条件 break; } } if(flag)//满足条件 { node[t]=i; v[i]=1; dfs(t+1); v[i]=0;//这一步很重要 } } } return ; } int main() { dfs(0); printf("count=%d\n",coun); }
最终结果给出了92种情况,与网上无差。
之后参考了《挑战程序设计》p193页,发现思想与第一种方法无差
但是,他给出了另外一种更高效的解法。
定义的bool类型为二维的
bool vis[3][18],可以更加高效的实现算法:
改进版代码如下:
#include<cstdio> #include<queue> #include<stack> #include<string> #include<cstdlib> #include<cstring> #include<cmath> #include<iomanip> #include<algorithm> #include<iostream> #define PI acos(-1) #define ull unsigned __int64 #define Min(a,b) ((a>b)?b:a) #define Max(a,b) ((a>b)?a:b) #define INF 1000000007 using namespace std; bool vis[3][18]={0}; int node[8]; int coun=0; void dfs(int t) { if(t==8) { printf("(%d,%d)",0,node[0]); for(int i=1;i<8;i++) printf(" (%d,%d)",i,node[i]); printf("\n"); coun++; return ; } for(int i=0;i<8;i++) { if(!vis[0][i]&&!vis[1][i+t]&&!vis[2][t-i+8]) //V[0][i]表示记忆,vis[1][i]表示左下右上的斜线,vis[2][i]表现左上右下 { vis[0][i]=vis[1][i+t]=vis[2][t-i+8]=1; node[t]=i; dfs(t+1); vis[0][i]=vis[1][i+t]=vis[2][t-i+8]=0; } } return ; } int main() { dfs(0); printf("count=%d\n",coun); }
只用了一层循环,这告诉了我们一点:
学好数学是很重要的
相关文章推荐
- 探寻main函数的“标准”写法,以及获取main函数的参数、返回值
- XUtils的简单使用
- EasyUI datagrid行编辑-选课系统轮次管理
- OpenCV学习08
- C++中的句柄类
- 视觉跟踪入门概念
- CodeForces 616 C. The Labyrinth(dfs)
- 修改系统底部导航栏
- 高质量PHP代码的50个实用技巧:非常值得收藏
- java获取客户端真实地址IP
- React—组件生命周期详解
- CDOJ 1277 智商杯考试 每周一题 div2 二分+数学
- 总结前端常用控件和疑难杂症的解决方法
- iOS项目本地git添加和删除
- 在Linux系统上开启Initrd文件系统的方法
- Linux---Nginx平滑升级graceful
- alert支持回调函数,实现confirm/promp等模态框【基于jQuery.bootbox 】
- oc语言的基本知识
- 微信SDK开发学习
- Windows最常用的8个网络CMD命令总结