1213:八皇后问题
【题目描述】
在国际象棋棋盘上放置八个皇后,要求每两个皇后之间不能直接吃掉对方。
【输入】
(无)
【输出】
按给定顺序和格式输出所有八皇后问题的解(见样例)。
【输入样例】
(无)
【输出样例】
No. 1 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 0 0 1 0 0 0 0 0 No. 2 1 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 ...以下省略
- 思路:利用dfs搜索每一行,搜索过程中搜到可以放皇后的位置,利用一维数组将其所在列,所在对角线进行标记,直到搜索完整个棋盘的下一次终止搜索。 还需注意本题的打印方式是按列打印(算是一个小小的陷阱吧)
#include<iostream>
using namespace std;
const int N=1e2+10;
int n=8;
int a[N][N];//棋盘
int queen[N];//标记皇后所在列
/*
对于左上到右下的斜对角线,同一条对角线上i-j+n的值相同
对于右上到左下的斜对角线,同一条对角线上i+j的值相同
*/
int vis_ltor[N], vis_rtol[N];//标记皇后所在的对角线
int sum=1;
//搜索每一行
void dfs(int i)
{
//终止条件
if (i == n+1)
{
printf("No. %d\n", sum++);
//注意题目要求的是按列打印
for (int j = 1; j <= n; j++)
{
for (int i = 1; i <= n; i++)
{
cout << a[i][j] << " ";
}cout << endl;
}
return;
}
//枚举方案
for (int j = 1; j <= n; j++)
{
//标记皇后所在的列以及对角线
if (!queen[j] && !vis_ltor[i - j + n] && !vis_rtol[i + j])
{
a[i][j]=queen[j] = vis_ltor[i - j + n] = vis_rtol[i + j] = 1;
//进入下一行继续搜索
dfs(i + 1);
//回溯
a[i][j] = queen[j] = vis_ltor[i - j + n] = vis_rtol[i + j] = 0;
}
}
}
int main()
{
dfs(1);
return 0;
}
1214:八皇后
|
上题代码稍作修改,将打印处换成打印每个皇后所在列,另外还有行列的关系发生变化
#include<iostream>
using namespace std;
const int N=1e2+10;
int n=8;
int m;
bool a[N][N];//棋盘
int queen[N];//标记皇后所在列
int vis_ltor[N], vis_rtol[N];//标记皇后所在的对角线
int sum=0;
int k;
//搜索每一行
void dfs(int i)
{
//终止条件
if (i == n + 1)
{
++sum;
if (sum ==k ) {
//注意题目要求的是按列打印
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
if (a[i][j])
cout <<j;
}
}cout << endl;
}
return;
}
//枚举方案
for (int j = 1; j <= n; j++)
{
//标记皇后所在的列以及对角线
if (!queen[j] && !vis_ltor[i - j + n] && !vis_rtol[i + j])
{
a[i][j]=queen[j] = vis_ltor[i - j + n] = vis_rtol[i + j] = 1;
//进入下一行继续搜索
dfs(i + 1);
//回溯
a[i][j] = queen[j] = vis_ltor[i - j + n] = vis_rtol[i + j] = 0;
}
}
}
int main()
{
cin >> m;
while (m--)
{
cin >> k;
sum = 0;
dfs(1);
}
return 0;
}