藍橋杯 基礎練習 2n皇后問題【DFS + 回溯】
阿新 • • 發佈:2019-01-24
時間限制:1.0s 記憶體限制:512.0MB
問題描述
給定一個n*n的棋盤,棋盤中有一些位置不能放皇后。現在要向棋盤中放入n個黑皇后和n個白皇后,使任意的兩個黑皇后都不在同一行、同一列或同一條對角線上,任意的兩個白皇后都不在同一行、同一列或同一條對角線上。問總共有多少种放法?n小於等於8。
輸入格式
輸入的第一行為一個整數n,表示棋盤的大小。
接下來n行,每行n個0或1的整數,如果一個整數為1,表示對應的位置可以放皇后,如果一個整數為0,表示對應的位置不可以放皇后。
輸出格式
輸出一個整數,表示總共有多少种放法。
樣例輸入
4
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
樣例輸出
2
樣例輸入
4
1 0 1 1
1 1 1 1
1 1 1 1
1 1 1 1
樣例輸出
0
題意: 略
分析: 和普通的皇后問題類似,先放第一個皇后,再放第二個,只不過我們在記錄下第一個皇后放的位置,然後dfs即可這裡陣列定義的有點亂,程式碼註釋下
參考程式碼
#include <bits/stdc++.h>
using namespace std;
int vis[21][21]; //皇后是否可放
bool v[21][21]; //第一個皇后的位置
bool h[21],z[21],f[21]; //第一個皇后 放的 行,還有兩條斜線
bool Z[21],F[21],H[21]; //第二個同上
int n,res; //res 記錄答案
bool check(int x,int y) {
if(vis[y][x] && !h[y] && !z[x + y] && !f[y - x + 8]) return true;
return false;
}
bool check1(int x,int y) {
if(!v[x][y] && vis[y][x] && !H[y] && !Z[x + y] && !F[y - x + 8 ]) return true;
return false;
}
void dfs(int idx1, int idx2) {
if(idx2 > n) { // 找到答案
res++;
return ;
}
if(idx1 > n) { // 第一個皇后已放好
for (int i = 1; i <= n; i++) {
if(check1(idx2,i)) {
H[i] = true;
Z[idx2 + i] = true;
F[i - idx2 + 8] = true;
dfs(idx1,idx2 + 1);
H[i] = false;
Z[idx2 + i] = false;
F[i - idx2 + 8] = false;
}
}
return ;
}
for (int i = 1; i <= n; i++) { // 放第一個皇后
if(check(idx1,i)) {
h[i] = true;
z[idx1 + i] = true;
f[i - idx1 + 8] = true;
v[idx1][i] = true;
dfs(idx1 + 1,idx2);
v[idx1][i] = false;
h[i] = false;
z[idx1 + i] = false;
f[i - idx1 + 8] = false;
}
}
}
int main() {
cin>>n;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
cin>>vis[i][j];
}
}
dfs(1,1);
cout<<res<<endl;
return 0;
}