AcWing 1432. 棋盘挑战
题意:
N皇后问题。
每行只可以放一个,每列也只可以放一个。
还要保证对角线不冲突。
输出:
按字典序输出前3组答案。
最后输出总方案数。
思路:
首先对于摆放问题
暴力dfs就好,因为行不冲突,所以每行只可以放一个棋子,所以从这里入手。
判断冲突的时候要注意一下优化
:
- 暴力查看每一行的每一列,假如当前列 c o l [ i ] col[i] col[i]没有放元素,那么可能可以放。
- 之后看是否对角线冲突,可以观察得到
对于每个对左对角线
上的值,都是 x − y x-y x−y,那么就可以用一个数组,来标记对角线,来防止冲突。(注意
x-y,可能出现负数,那么加一个n,防止越界)(右对角线,同理)
至于输出
ans<=3时,直接输出即可。
反思:
- 本题主要考察对角线上的性质,通过一个数组去判断对角线的冲突。
AC
# include <bits/stdc++.h>
using namespace std;
int ans, n, col[14], ll[30], rl[30];
bool check(int x, int y){
if(col[y]||ll[x-y+n]||rl[x+y])return false;
return true;
}
void dfs(int x){
if(x>n){
ans++;
if(ans<=3){
int row[14]{
};
for(int co = 1; co <= n; co++) row[col[co]] = co;
for(int ro = 1; ro <= n; ro++) cout<<row[ro]<<' ';
cout<<endl;
}
return;
}
for(int y = 1; y <= n; y ++ ){
if(!check(x,y))continue;
col[y] = x;
ll[x-y+n] = rl[x+y] = 1;
dfs(x+1);
ll[x-y+n] = rl[x+y] = 0;
col[y] = 0;
}
}
int main(){
cin>>n;
dfs(1);
cout<<ans<<endl;
return 0;
}
AC2
# include <bits/stdc++.h>
# define mst(x,a) memset(x,a, x)
using namespace std;
int n;
int vis[14], ans;
//vector<vector<int> > res;
int ll[30], rl[30];
bool check(int x, int y){
if(ll[x-y+n]||rl[x+y])return false;
return true;
}
//int path[14][3];
map<vector<int>,int>ma;
void dfs(int x){
if(x==n+1){
ans++;
// res.push_back()
vector<int> res(15);
for(int i = 1; i <= n; i ++ ) res[vis[i]] = i;
ma[res] = 1;//cout<<res[i]<<' ';
//cout<<endl;
return ;
}
for(int y = 1; y <= n; y ++ ){
if(vis[y]||!check(x,y))continue;
vis[y] = x;
ll[x-y+n] = rl[x+y] = 1;
dfs(x+1);
ll[x-y+n] = rl[x+y] = 0;
vis[y] = 0;
}
}
int main(){
cin>>n;
dfs(1);
int cnt = 0;
for(auto x : ma){
if(cnt++ == 3)break;
auto v = x.first;
for(int i = 1; i <= n; i ++ )cout<<v[i]<<' ';
cout<<endl;
}
cout<<ans<<endl;
return 0;
}