N皇后
问题描述:
- 在n×n格的棋盘上放置彼此不受攻击的n个皇后。
- 按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。n皇后问题等价于在n×n格的棋盘上放置n个皇后,任何两个皇后不放在同一行或同一列或同一斜线上。
- 编程要求:找出一个n×n格的棋盘上放置n个皇后并使其不能互相攻击的所有方案。
-
#include <bits/stdc++.h>
using namespace std;
#define NUM 20
int n; //棋盘的大小
int x[NUM]; //解向量
int sum; //当前已经找到的可行方案数
//形参t是回溯的深度
inline bool Place(int t)
{
int i;
for(i=1;i<t;i++)
{
/*1.由于每一列只放置一个皇后,所以不会出现同列的问题,不用判断合法性。
2.对于每一行,假设已经放置到t列,只要判断 ,i=1, 2, …, t-1互不相同即可。
3. 对于对角线的判断,可以看成是斜率为±1的两条直线,经过两点(i,x[i])和(t,x[t]):
|t-i/(x[t]-x[i])|=1;(t-i)的绝对值=(x[i]-x[t])的绝对值
*/
if((abs(t-i)==abs(x[i]-x[t]))||(x[i]==x[t]))
return false;
}
return true;
}
//形参t是回溯的深度,从1开始
void Backtrack(int t)
{
int i;
//到达叶子节点,获得一个方案,累加
if(t>n)
{
sum++;
for(i=1;i<=n;i++)
{//输出该方案
cout<<x[i]<<" ";
}
cout<<endl;
}else
for(i=1;i<=n;i++)
{
x[t]=i;
if(Place(t))Backtrack(t+1);
}
}
int main()
{
cin>>n;
Backtrack(1);
cout<<"Total:"<<sum<<endl;
return 0;
}
/*DFS深度优先搜索算法(depth first search):一种用于遍历或搜索树或图的算法。
沿着树的深度遍历树的节点,尽可能深的搜索树的分支。
当节点v的所在边都己被探寻过或者在搜寻时结点不满足条件,
搜索将回溯到发现节点v的那条边的起始节点。
整个进程反复进行直到所有节点都被访问为止。
属于盲目搜索,最糟糕的情况算法时间复杂度为O(!n)。*/
2N皇后
问题描述:
给定一个n*n的棋盘,棋盘中有一些位置不能放皇后。现在要向棋盘中放入n个黑皇后和n个白皇后,使任意的两个黑皇后都不在同一行、同一列或同一条对角线上,任意的两个白皇后都不在同一行、同一列或同一条对角线上。问总共有多少种放法?n小于等于8。
输入格式
输入的第一行为一个整数n,表示棋盘的大小。
接下来n行,每行n个0或1的整数,如果一个整数为1,表示对应的位置可以放皇后,如果一个整数为0,表示对应的位置不可以放皇后。
输出格式
输出一个整数,表示总共有多少种放法。
样例输入
4
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
样例输出
2
样例输入
4
1 0 1 1
1 1 1 1
1 1 1 1
1 1 1 1
样例输出
0
#include <bits/stdc++.h>
using namespace std;
const int maxn=9;
int n;
int Q[maxn][maxn];
int black[maxn]={0};
int white[maxn]={0};
int sum;//当前已经找到的可行方案数
bool placeBlack(int t)
{
for(int i=1;i<t;i++)
{
if(abs(black[i]-black[t])==abs(i-t)||black[i]==black[t])
return false;
}
return true;
}
bool placeWhite(int t)
{
for(int i=1;i<t;i++)
{
if(abs(white[i]-white[t])==abs(i-t)||white[i]==white[t])
return false;
}
return true;
}
void dfs_white(int t)
{
if(t>n)
{
sum++;
}
for(int i=1;i<=n;i++)
{
if(black[t]==i)//表示第t列的第i行位置已经被黑皇后占用
continue;
if(Q[t][i]==0)//判断前提条件是否成立
continue;
white[t]=i;//把第t列的白皇后放在i行
if(placeWhite(t))dfs_white(t+1);//如果可以放,则递归
}
}
void dfs_black(int t)
{
if(t>n)//黑皇后处理完再处理白皇后
{
dfs_white(1);
}
for(int i=1;i<=n;i++)
{
if(Q[t][i]==0)//判断前提条件是否成立
continue;
black[t]=i;//把第t列的黑皇后放在i行
if(placeBlack(t))dfs_black(t+1);//如果可以放,则递归
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
cin>>Q[i][j];//定义棋盘
}
}
sum=0;
dfs_black(1);
cout <<sum<< endl;
return 0;
}