タイトルの説明
n * nのボードが与えられた場合、クイーンには使用できないボード上の位置がいくつかあります。ここで、チェス盤にn個の黒の女王とn個の白い女王を配置する必要があります。これにより、2つの黒の女王が同じ行、同じ列、または同じ対角線にならず、2つの白の女王が同じ行にありません。同じ列または同じ対角線上。合計何種類のリリース方法を尋ねますか?nは8以下です。
入力
入力の最初の行は整数nで、チェス盤のサイズを示します。
次のn行では、各行に0または1のn個の整数があります。整数が1の場合、対応する位置をクイーンとして配置できることを示します。整数が0の場合、対応する位置をクイーンとして配置できないことを示します。アウトプット
整数が出力され、合計で何種類のputメソッドが使用されているかを示します。
入力例
4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1出力例
2
元のタイトルのリンク:[Blue Bridge Cup] [Basic Practice VIP] 2n Queen Question
2nクイーンの問題を調べる前に、古典的な質問タイプのバックトラッキングを理解する必要があります。8クイーンの問題です。
1.最初に8つのクイーンの質問を貼り付けます。
8 * 8のボードが与えられます。次に、8つのクイーンをボードに配置して、2つのクイーンが同じ行、同じ列、または同じ対角線にならないようにします。
明確にする必要があります:
- 1.クイーン8人が入れられます
- 2. 1行に1つずつ入力します(1つしかありません)
- 3.各列に1つ(および1つだけ)もあります。
- 4.完全な配置または8つのforループを使用する場合、結果はほとんど悲劇的です
キーコード:
int vis[10]; //vis[i]=1 表示第i【列】被访问过了,后面此列不被访问
int a[10]; //a[i]=j 表示第i个皇后(第i行)的位置为j->a[j]
void dfs(int step,int n) { //安排第step个皇后(即第step【行】)
if(step==n+1) { //递归边界,表示n个皇后已经安排好了
cnt++;
} else {
for(int i=1; i<=n; i++) { //遍历i列
if(vis[i]==0) { //第i列必须是之前没访问过得一列
bool tag = true;
for(int j=1; j<step; j++) { //遍历a数组1~step:查找与之前已经定好位的皇后是否冲突
if(step-j == i-a[j] || step-j == a[j]-i) {
//当前位置:(step,i) 之前位置(j,a[j]),若他们在对角线上,则斜率(step-j)/(i-a[j])为1或-1
tag = false;
break;
}
}
if(tag) { // i列符合条件
vis[i]=1; // 访问
a[step] = i;
dfs(step+1,n);// 安排下一个皇后
vis[i]=0; // 回溯:恢复DFS之前的状态
}
}
}
}
}
質問タイプのバリアントのアプリケーションの近似、チェッカーボード多項式を参照してください
第二に、2nクイーンへの移行の問題:
違いは、各行の黒の女王に加えて、白の女王もいるということです。
したがって、上記の方法で黒の女王の場所を見つけた後、それを1回見つけて白の女王を見つける必要があります。2つの女王が配置された後でのみ、次の位置の行に入ることができます。
つまり、visの配列でもqueenの配列でも、2つのコピーを準備する必要があります。
完全なコードを以下に示します。
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int cnt = 0;
int map[10][10]; //存储地图
int visb[10]; //visb[i]=1第i列已经有了黑皇后
int visw[10]; //白皇后,同上
int black[10]; //black[i]=j 表示第i个黑皇后(i行)在第j列
int white[10]; //白皇后的位置,同上
void dfs(int step,int n) { //step代表第几行,要安排第几个皇后
if(step==n+1) {
cnt++;
} else {
for(int i=1; i<=n; i++) { //第step行遍历i列(i->1-n)
bool black_tag = true;
if(visb[i]==0 && map[step][i]==1) {
for(int j=1; j<step; j++) { //跟之前已经定好位的皇后做比较
if(step-j == i-black[j] || step-j == black[j]-i) { //斜对角方向 (step,i)和(j,a[j])的斜率为1或-1
black_tag = false;
break;
}
}
if(black_tag) {
visb[i]=1; //这一列有皇后了,后面一整列都不能访问
black[step] = i; //(step,i)->(step,a[step])
for(int k=1; k<=n; k++) {
if(k==i) continue;
bool white_tag = true;
if(visw[k]==0 && map[step][k]==1) {
for(int j=1; j<step; j++) { //跟之前已经定好位的皇后做比较
if(step-j == k-white[j] || step-j == white[j]-k) { //斜对角方向 (step,k)和(j,a[j])的斜率为1或-1
white_tag = false;
break;
}
}
if(white_tag) {
visw[k]=1;
white[step] = k;
dfs(step+1,n); //搜索下一行(下一个皇后)
visw[k]=0;
}
}
}
visb[i]=0;
}
}
}
}
}
int main() {
int n;
cin>>n;
for(int i=1; i<=n; i++) {
for(int j=1; j<=n; j++) {
cin>>map[i][j];
}
}
dfs(1,n);
cout<<cnt;
return 0;
}