洛谷 P1219. 八皇后--dfs两种写法
[USACO1.5] 八皇后 Checker Challenge
题目描述
一个如下的 \(6 \times 6\) 的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行、每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子。
上面的布局可以用序列 \(2\ 4\ 6\ 1\ 3\ 5\) 来描述,第 \(i\) 个数字表示在第 \(i\) 行的相应位置有一个棋子,如下:
行号 \(1\ 2\ 3\ 4\ 5\ 6\)
列号 \(2\ 4\ 6\ 1\ 3\ 5\)
这只是棋子放置的一个解。请编一个程序找出所有棋子放置的解。
并把它们以上面的序列方法输出,解按字典顺序排列。
请输出前 \(3\) 个解。最后一行是解的总个数。
输入格式
一行一个正整数 \(n\),表示棋盘是 \(n \times n\) 大小的。
输出格式
前三行为前三个解,每个解的两个数字之间用一个空格隔开。第四行只有一个数字,表示解的总数。
样例 #1
样例输入 #1
6
样例输出 #1
2 4 6 1 3 5
3 6 2 5 1 4
4 1 5 2 6 3
4
提示
【数据范围】
对于 \(100\%\) 的数据,\(6 \le n \le 13\)。
题目翻译来自NOCOW。
USACO Training Section 1.5
题解
1
从前往后枚举所有点放皇后的情况 + 剪枝 优化掉一层对行的枚举 优化对正反对角线的枚举 利用行和列去表示对角线
#include <bits/stdc++.h>
using namespace std;
const int N = 30; // 13 * 2 - 1
bool col[N], dg[N], udg[N];
int n;
int cnt;
char g[N][N];
void dfs(int u)
{
if (u > n)
{
cnt ++ ;
if(cnt <= 3)
{
for (int i = 1; i <= n; i ++ )
{
for (int j = 1; j <= n; j ++ )
{
if (g[i][j] == 'Q')
{
printf("%d ", j);
}
}
}
cout << endl;
}
return;
}
for (int i = 1; i <= n; i ++ )
{
if (!col[i] && !dg[u + i] && !udg[n - u + i]) //分别对应 列 对角线和反对角线
{
col[i] = dg[u + i] = udg[n - u + i] = true;
g[u][i] = 'Q';
dfs(u + 1);
col[i] = dg[u + i] = udg[n - u + i] = false;
g[u][i] = '.';
}
}
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i ++ )
{
for (int j = 1; j <= n; j ++ )
{
g[i][j] = '.';
}
}
dfs(1);
printf("%d\n", cnt);
return 0;
}
2
这个搜索方案没有办法确保按照字典序输出棋盘
这种搜索方法就不用我们用循环去枚举列数了 一个点一个点的搜 每个点两种情况 放皇后和不放皇后
#include <bits/stdc++.h>
using namespace std;
const int N = 30; // 13 * 2 - 1
bool row[N], col[N], dg[N], udg[N];
int n;
int cnt;
char g[N][N];
void dfs(int x, int y, int s) //行数 列数 当前皇后个数
{
if (x > n) //当前行枚举完 换到第二行第一个格子开始枚举
{
y ++;
x = 1;
}
if (y > n)
{
if (s == n)
{
//cout << 1;
cnt ++ ;
{
for (int i = 1; i <= n; i ++ )
{
for (int j = 1; j <= n; j ++ )
{
if (g[i][j] == 'Q')
printf("%d ", j);
}
}
cout << endl;
}
}
return; //一定要放在if(s == n)判断的外面 只要这种情况搜完了 不管是否是合法情况 都要返回
}
//该格子不放皇后
g[x][y] = '.';
dfs(x + 1, y, s);
//该格子放皇后
if (!row[x] && !col[y] && !dg[x + y] && !udg[n - x + y])
{
row[x] = col[y] = dg[x + y] = udg[n - x + y] = true;
g[x][y] = 'Q';
dfs(x + 1, y, s + 1);
row[x] = col[y] = dg[x + y] = udg[n - x + y] = false;
g[x][y] = '.';
}
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i ++ )
{
for (int j = 1; j <= n; j ++ )
{
g[i][j] = '.';
}
}
dfs(1, 1, 0);
printf("%d\n", cnt);
return 0;
}