1. 程式人生 > >藍橋杯 基礎練習 2n皇后問題【DFS + 回溯】

藍橋杯 基礎練習 2n皇后問題【DFS + 回溯】

時間限制: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; }