Problem:棋盤挑戰
阿新 • • 發佈:2021-02-09
Problem Description
給定一個 N × N 的棋盤,請你在上面放置 N 個棋子,要求滿足:
- 每行每列都恰好有一個棋子
- 每條對角線上都最多隻能有一個棋子
上圖給出了當 N = 6 時的一種解決方案,該方案可用序列 2 4 6 1 3 5 來描述,該序列按順序給出了從第一行到第六行,每一行擺放的棋子所在的列的位置。
請你編寫一個程式,給定一個 N×N 的棋盤以及 N 個棋子,請你找出所有滿足上述條件的棋子放置方案。
Input Format
共一行,一個整數 N。
Output Format
共四行,前三行每行輸出一個整數序列,用來描述一種可行放置方案,序列中的第 i 個數表示第 i 行的棋子應該擺放的列的位置。
這三行描述的方案應該是整數序列字典序排在第一、第二、第三的方案。
第四行輸出一個整數,表示可行放置方案的總數。
* Scope of Data*
6 ≤ N ≤ 13
Sample Input
Sample Output
Idea
運用DFS思想從第1行開始對每一列進行列舉判斷
Program Code
#include <iostream>
#include <algorithm>
using namespace std;
#define x row
#define y column
#define P primary_diagonal
#define S secondary_diagonal
const int N = 15;
int n;
int cnt, a[N]; //cnt表示可通過方案數,a[N]表示具體方案
int col[N], P[2 * N], S[2 * N]; //在n * n矩陣中,斜率為1的對角線有2n - 1條,斜率為-1的對角線亦然
void bfs(int x) //定義深搜函式
{
if(x > n) //表示最後一行也得到結果,生成完整的一組方案
{
cnt ++; //更新方案個數
if(cnt <= 3) //輸出前3個方案
{
for(int i = 1; i <= n; ++ i)
cout << a[i] << ' ';
cout << endl;
}
}
for(int y = 1; y <= n; ++ y) //每行從第1列開始列舉列
{
if(!col[y] && !P[x + y] && !S[x -y + n]) //若該列、主對角線和副對角線均沒有違規(x - y + n 是為防止出現負數,運用了移碼的思想)
{
a[x] = y; //將列值賦值給對應的答案陣列
col[y] = P[x + y] = S[x -y + n] = 1; //更新相應陣列
bfs(x + 1); //遞迴執行下一行
//恢復現場
a[x] = col[y] = P[x + y] = S[x -y + n] = 0;
}
}
}
int main()
{
cin >> n; //輸入
bfs(1); //從第一行開始執行函式
cout << cnt; //輸出總結果
return 0;
}
- If you have any questions,please feel free to communicata with me.