Problem Description
给定一个 N × N 的棋盘,请你在上面放置 N 个棋子,要求满足:
- 每行每列都恰好有一个棋子
- 每条对角线上都最多只能有一个棋子
上图给出了当 N = 6 时的一种解决方案,该方案可用序列 2 4 6 1 3 5 来描述,该序列按顺序给出了从第一行到第六行,每一行摆放的棋子所在的列的位置。
请你编写一个程序,给定一个 N×N 的棋盘以及 N 个棋子,请你找出所有满足上述条件的棋子放置方案。
Input Format
共一行,一个整数 N。
Output Format
共四行,前三行每行输出一个整数序列,用来描述一种可行放置方案,序列中的第 i 个数表示第 i 行的棋子应该摆放的列的位置。
这三行描述的方案应该是整数序列字典序排在第一、第二、第三的方案。
第四行输出一个整数,表示可行放置方案的总数。
* Scope of Data*
6 ≤ N ≤ 13
Sample Input
Sample Output
Idea
运用DFS思想从第1行开始对每一列进行枚举判断
Program Code
#include <iostream>
#include <algorithm>
using namespace std;
#define x row
#define y column
#define P primary_diagonal
#define S secondary_diagonal
const int N = 15;
int n;
int cnt, a[N]; //cnt表示可通过方案数,a[N]表示具体方案
int col[N], P[2 * N], S[2 * N]; //在n * n矩阵中,斜率为1的对角线有2n - 1条,斜率为-1的对角线亦然
void bfs(int x) //定义深搜函数
{
if(x > n) //表示最后一行也得到结果,生成完整的一组方案
{
cnt ++; //更新方案个数
if(cnt <= 3) //输出前3个方案
{
for(int i = 1; i <= n; ++ i)
cout << a[i] << ' ';
cout << endl;
}
return;
}
for(int y = 1; y <= n; ++ y) //每行从第1列开始枚举列
{
if(!col[y] && !P[x + y] && !S[x -y + n]) //若该列、主对角线和副对角线均没有违规(x - y + n 是为防止出现负数,运用了移码的思想)
{
a[x] = y; //将列值赋值给对应的答案数组
col[y] = P[x + y] = S[x -y + n] = 1; //更新相应数组
bfs(x + 1); //递归执行下一行
//恢复现场
a[x] = col[y] = P[x + y] = S[x -y + n] = 0;
}
}
}
int main()
{
cin >> n; //输入
bfs(1); //从第一行开始执行函数
cout << cnt; //输出总结果
return 0;
}
- If you have any questions,please feel free to communicate with me.