八皇后问题(dfs)
八皇后问题:八行八列国际象棋棋盘中,每一行每一列每一条斜线上只能放置一个皇后,不能冲突,能有多少种放置方式
算法:深搜 dfs(depth-first search)dfs的思想就是从初始状态出发,下一步可能有多种状态,选其中一个状态深入,到达新的状态;直到无法继续深入,退回到前一步,转移到其他状态,然后再深入下去。
dfs:可以遍历每一种情况,直到找到解法;空间要求小;时间要求高;为了降低时间复杂度,进行剪枝;一定要回溯,收拾现场,不然影响下一条路走;精华就是回溯和剪枝;dfs其实就是递归
具体看代码实现(下面代码为n皇后问题的解决,两种dfs方法)
#include <bits/stdc++.h>
using namespace std;
const int N = 50;
int n;
char g[N][N]; //记录图 graph
int row[N],col[N],dg[N],udg[N];
int cnt;
int s;
void dfs1(int u) //每一行为递归的一层
{
if (u==n) //递归要提前设置好出口
{
cout<<"case"<<++cnt<<":"<<endl;
for (int i=0;i<n;i++) puts(g[i]);
puts("");
return;
}
for (int i=0;i<n;i++)
{
//剪枝
if (!col[i]&&!dg[i+u]&&!udg[i-u+n])//b==y+x||b==y-x+n; //对每一行中的每一列判断是否放皇后,如果该行某列没放过皇后,正对角线与反对角线也没放过就放置
{
g[u][i]='Q';
col[i]=dg[i+u]=udg[i-u+n]=1;
dfs1(u+1); //递归到下一行
col[i]=dg[i+u]=udg[i-u+n]=0; //回溯(立马收拾现场)
g[u][i]='.';
}
}
}
void dfs2(int x,int y,int s) //每一点为递归的一层 ,s代表已经放置皇后的个数
{
if (y==n) y=0,x++; //y越界就坐标跳到下一行第一位
if (x==n) //x越界则说明原先的0~n-1行过了一遍了
{
if (s==n) //放置完了皇后
{
cout<<"case"<<++cnt<<":"<<endl;
for (int i=0;i<n;i++) puts(g[i]);
puts("");
}
return; // 无论有没有放置完皇后都要往回走了
}
//不放皇后
dfs2(x,y+1,s);
//放皇后
if (!row[x]&&!col[y]&&!dg[y+x]&&!udg[y-x+n]) //剪枝
{
g[x][y]='Q';
row[x]=col[y]=dg[y+x]=udg[y-x+n]=1;
dfs2(x,y+1,s+1); //dfs2(x+1,0,s+1);
row[x]=col[y]=dg[y+x]=udg[y-x+n]=0; //回溯(立马收拾现场)
g[x][y]='.';
}
}
int main()
{
cin>>n;
for (int i=0;i<n;i++)
for (int j=0;j<n;j++)
g[i][j]='.';
//dfs1(0);
dfs2(0,0,0);
cout<<"ans="<<cnt;
return 0;
}