close

 

問題描述 :

如何在棋盤上擺滿彼此不會互相攻擊到的皇后,一直以來是在西洋棋盤上一個很經典也很有趣的問題。

在西洋棋中,皇后的攻擊範圍是所有棋子裡面最大的,一只皇后 (Q) 可以控制縱橫與兩條斜對角線上的所有格子,範圍如下圖深色的格子所示,

一般而言,我們在 NxN (N≥4) 以上大小的棋盤,都可以擺上 N 只皇后而不互相攻擊,範例如下所示。

如果在 NxN 的棋盤上指定一只皇后的位置,請設計程式檢查是否可以擺上剩餘的 N-1 只皇后。

輸入說明 :

輸入之資料格式,一列資料代表一筆測資。每一列中,共有三個整數,第一個整數 N(3<N<9) 表示是 NxN 大小的棋盤,第二個整數 x (0~N-1) 及第三個整數 y (0~N-1) 用來標示給定的皇后位置。每一個整數之間以空白字元分隔。測資可能有多筆,請繼續讀取到沒有資料為止。

輸出說明 :

對於每一筆測資,如果可以把所有 N 只皇后都擺上去的話,請輸出 YES ,並在後面括號輸出所有合法的擺放方式數;如果沒辦法的話,請輸出 NO ,每一個測試範例的結果輸出一行。

思路: 八皇后問題, 首先你必須要懂八皇后怎麼放的, 用的是回溯法, 用一個一維陣列就能記錄皇后xy位置, 因為皇后每一行只能有一個,

比如 第1行皇后在第5個位置 那麼 queen[1] = 5, 第0行皇后在第1個位置 那麼 queen[0] = 1

所以從第0行開始放, 然後第0行又可以放從0~n, 每個都放放看。

那麼怎麼樣快速判斷皇后是否在同一個垂直線或在斜線呢, 水平線已經處理完了因為是一行一行放的。 

所以就用到剛剛紀錄皇后位置的陣列, 從第0行開始掃描到第k行(k是剛剛做到哪一行) 比對陣列有沒有一樣 一樣代表垂直線兩個皇后

斜線的話用斜率 = 1, 又斜率 = (y-y0)/(x-x0) , 所以就直接用 y-y0 = x - x0, 來判斷是否同一個斜線。

如果都沒有上述的狀況, 那麼就繼續坐下一行。

依此類推, 做到n個

這題題目給了一個皇后位置, 所以說那行皇后不能給他用其他位置, 也就是說遇到那行只能做1次。就是不能給那行其他皇后位置,會出錯,我之前卡在這。

程式碼:

#include <iostream>
#include <cstring>
#include <cmath>

using namespace std;
int queen[10];
int n, x, y, ans;
bool canPlaceQ(int k){
    for(int i = 0; i < k; ++i){
        if(queen[i] == queen[k] || abs(k - i) == abs(queen[i] - queen[k]))
            return false;
    }
    return true;
}
void dfs(int k){
    for(int j = 0; j < n; ++j){
        if(k == x){
            queen[k] = y;
            j = n;
        }
        else
            queen[k] = j;
        if(k == n - 1 && canPlaceQ(k)){
            ans++;
            return;
        }
        else if(canPlaceQ(k))
            dfs(k+1);
    }
}
int main()
{
    while(cin >> n >> x >> y){
        memset(queen, 0, sizeof queen);
        ans = 0;
        dfs(0);
        if(ans)
            cout << "YES" << '(' << ans << ")\n";
        else
            cout << "NO\n";
    }
    return 0;
}
 

 

arrow
arrow
    創作者介紹
    創作者 尾玉 的頭像
    尾玉

    louisfghbvc的部落格

    尾玉 發表在 痞客邦 留言(0) 人氣()