1. 程式人生 > >「JoyOI1080」N皇后

「JoyOI1080」N皇后

這是菜雞的我第一次寫這類題目:

題意:就是在N*N的棋盤上,每一行,每一列,所有的對角線都只能有一個棋子。

先分析:假若N=4;

    則為其中的一種答案。要輸出左右的解,肯定要枚舉出所有的解。那麼非常自然的想到遞迴!

  根據題意,每一步棋子都滿足,在一行,一列,兩個對角線。那麼怎麼解決呢?

  總體遞迴思路,肯定是以一行為處理單位的啦。每一行總從左到右是判斷是否這個棋子可以判斷。

不相鄰行的兩個棋子:

在這裡,我們先解決不為相鄰行時,兩個棋子不同列不同對角線問題。

不同列:直接定義一個數組,比如b[ 1 ]=1就表示第1列已經擺了一個棋子了。那麼後面的棋子直接判斷就行了。

不同列:

      很明顯在出現這種情況之前一定會出現這種擺法:所以根本不用擔心這種情況的發生。

相鄰行的兩個棋子:

我們解決怎樣判斷同一列,在兩個對角線中。

不同列:直接定義一個數組,比如b[ 1 ]=1就表示第1列已經擺了一個棋子了。那麼後面的棋子直接判斷就行了。

對角線一:  假設第一個點座標為(x, y)那麼,相鄰行並且同對角線的下一個點的座標是就是(x+1, y-1),對吧。是不是找到規律了。

     x+y=(x+1)+(y-1)  這樣就定義一個數組c[],  那麼 c[x+y]=1就可以表示點(x, y)所在的這類這條對角線已經有一個棋子。

對角線二:這類對角線的上的點的座標變化都是橫縱座標各自加1.這其實很好辦,每個座標都滿足x-y+n=k,每一條對角線對應唯一的一          

           個k值.至於x,y誰在前誰在後都無所謂,關鍵是抵消加1這個操作。那麼定義d[ x-y+n ]=1表示這個對角線已經有了一個棋子。

#include<iostream>
using namespace std;
int n, sum, a[15];
bool b[100], c[100], d[100];
void print(){
    sum++;
    if (sum <= 3){
        
for (int i = 1; i <= n; ++i) { cout << a[i] << " \n"[(i != n ? 0 : 1)]; } } } void queen(int i) { for (int j = 1; j <= n; ++j) { if ((b[j] == 0) && (c[i + j] == 0) && (d[i - j+n] == 0)) { a[i] = j; b[j] = 1; c[i + j] = 1; d[i - j + n] = 1; if (i == n)print(); else queen(i + 1); b[j] = 0; c[i + j] = 0; d[i - j + n] = 0; } } } int main() { cin >> n; queen(1); cout << sum << endl; return 0; }