DFS入门篇---八皇后!
2017-05-19 09:41
183 查看
让我们试着解决一些更有技巧的回溯问题。
八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
很快能想到如下思路:
1,逐行放置皇后,检查并保证不与已经放置的皇后冲突,并记录在数组中。
2,如果某一行无解了,返回上一行(回溯)。
3,填完了最后一行,记解的个数+1,同时输出数组中保存的解。
朴素的实现上述思路容易超时,下面引入一些小技巧
技巧:
1,如果不需要保存具体的解而只要计数,可不用数组进行解的记录。
2,把棋盘沿主对角线,副对角线,列分别编号,这样在做标记的时候可以在O(1)时间完成。
#include<bits/stdc++.h>
using namespace std;
bool v[3][256];
typedef pair<int,int> P;
vector<P> a; //用来保存解,但实际上只用保存纵坐标...这里用pair多此一举
int n,sum=0;
bool t=1; //表示是否输出了3个
inline bool judge(int i,int j) {
if(!v[0][j]&&!v[1][j-i+n]&&!v[2][i+j])
return 1;
return 0;
}
//逐行放置皇后
bool dfs(int i) {
if(i==n) {
sum++;
if(sum<=3) {
for(int j=0; j<a.size(); j++) {
printf("%d ",a[j].second+1);
}
putchar('\n');
} else t=0;
return 0;
}
//开始对这一行进行尝试
bool pre=0;
for(int j=0; j<n; j++) {
if(judge(i,j)==1) {
pre=1;
if(t) a.push_back(P(i,j));
v[0][j]=1; //列
v[1][j-i+n]=1; //主对角线
v[2][i+j]=1; //副对角线
if(dfs(i+1)==0) {
if(t) a.pop_back();
v[0][j]=0;
v[1][j-i+n]=0;
v[2][i+j]=0; //如果下一步dfs无解,证明这一步填错,退回
pre=0;
}
}
}
return pre;
}
int main() {
scanf("%d",&n);
dfs(0);
printf("%d",sum);
return 0;
}
八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
很快能想到如下思路:
1,逐行放置皇后,检查并保证不与已经放置的皇后冲突,并记录在数组中。
2,如果某一行无解了,返回上一行(回溯)。
3,填完了最后一行,记解的个数+1,同时输出数组中保存的解。
朴素的实现上述思路容易超时,下面引入一些小技巧
技巧:
1,如果不需要保存具体的解而只要计数,可不用数组进行解的记录。
2,把棋盘沿主对角线,副对角线,列分别编号,这样在做标记的时候可以在O(1)时间完成。
#include<bits/stdc++.h>
using namespace std;
bool v[3][256];
typedef pair<int,int> P;
vector<P> a; //用来保存解,但实际上只用保存纵坐标...这里用pair多此一举
int n,sum=0;
bool t=1; //表示是否输出了3个
inline bool judge(int i,int j) {
if(!v[0][j]&&!v[1][j-i+n]&&!v[2][i+j])
return 1;
return 0;
}
//逐行放置皇后
bool dfs(int i) {
if(i==n) {
sum++;
if(sum<=3) {
for(int j=0; j<a.size(); j++) {
printf("%d ",a[j].second+1);
}
putchar('\n');
} else t=0;
return 0;
}
//开始对这一行进行尝试
bool pre=0;
for(int j=0; j<n; j++) {
if(judge(i,j)==1) {
pre=1;
if(t) a.push_back(P(i,j));
v[0][j]=1; //列
v[1][j-i+n]=1; //主对角线
v[2][i+j]=1; //副对角线
if(dfs(i+1)==0) {
if(t) a.pop_back();
v[0][j]=0;
v[1][j-i+n]=0;
v[2][i+j]=0; //如果下一步dfs无解,证明这一步填错,退回
pre=0;
}
}
}
return pre;
}
int main() {
scanf("%d",&n);
dfs(0);
printf("%d",sum);
return 0;
}
相关文章推荐
- kb-01-a<简单搜索--dfs八皇后问题变种>
- 2016 UESTC Training for Search Algorithm & String A - Xiper的奇妙历险(1) 八皇后问题、dfs
- HDOJ 入门级深搜DFS 题目汇总,持续更新中,一路打怪升级
- 百练2754 八皇后(DFS)
- HDU1010 Tempter of the Bone (DFS入门)
- 八皇后问题 DFS,回溯剪枝 //http://poj.grids.cn/practice/2698
- dfs入门练习一
- [HDU]1016 DFS入门题
- poj1562 DFS入门
- nyoj 1282 部分和问题(入门题)(dfs)
- DFS专题(入门,经典为主)
- hdu 1312 Red and Black(dfs入门)
- Checker Challenge(dfs深度搜索 打印八皇后)
- 算法竞赛入门-回溯-7.4.1-八皇后问题
- 洛谷 1219 八皇后 【DFS】
- 图论入门———深度优先搜索实现二分图判定(dfs染色)
- HDU 1241 Oil Deposits(dfs入门级别模板题)
- 【算法入门】深度优先搜索(DFS)
- Vijos P1114 FBI树【DFS模拟,二叉树入门】
- 入门DFS