极简题解
2025-07-25 08:54:27
发布于:上海
14阅读
0回复
0点赞
题目大意
n×n 的跳棋棋盘,有n个棋子被放置在棋盘上,使得每行、每列有且只有一个
每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子。
并把它们以上面的序列方法输出,解按字典顺序排列。输出前 3 个解。然后输出一行,表示解的总个数。
思路分析
用深搜枚举每一个可能的位置,本次递归是本轮一行所有可能位置的枚举
确定一个位置后将他所在的列,左上右下对角线,左下右上对角线用是3个数组标记
后面的不能在这些位置上放棋子(行作为深搜递归的参数依次往下递归,无需记录)
放到最后一个时就找到了一种方法,输出并记录
代码实现
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n,cnt,a[110];
ll dy[110],da[110],db[110];
void dfs(ll x){ // x为行数,依次排列
if(x > n){ // 这时枚举到了最后一个,n行都成立,已经找出一个解
cnt++;
if(cnt <= 3){ // 只输出前3个
for(int i = 1;i <= n;i++){
cout << a[i] << " ";
}
cout << endl;
}
}
for(int i = 1;i <= n;i++){ // 从一列的第一个枚举到最后一1个
if(dy[i]==1 || da[x - i + n] || db[x + i]){
//dy为列数,依次排列
//da为左上到右下的数条对角线,
//规律为一条对角线中每个格子横纵坐标差相等
//所以下标用 x - i + n
//(因为有负数所以 +n 避免下标为负)
//db为右上到坐下的数条对角线,
//规律为一条对角线中每个格子横纵坐标和相等
//所以下标用 x + i
//(相加无负数,从1到 2n 的这几条)
continue;
}else{
dy[i] = 1;
da[x - i + n] = 1;
db[x + i] = 1; //标记这些行和列都不能放棋子
a[x] = i; //a记录坐标(即答案)
dfs(x + 1); //搜索下一个
dy[i] = 0;
da[x - i + n] = 0;
db[x + i] = 0; //当前不行,y,a,b重置回溯,再进入下一趟循环
}
}
return ;
}
int main(){
cin >> n;
dfs(1);
cout << cnt;
return 0;
}
全部评论 1
好厉害!!!
4天前 来自 上海
1
有帮助,赞一个