題解 P1219 八皇后

2022-01-14 04:54:32 字數 1956 閱讀 3087

寫在前面:

第一次認真寫題解qwq求讚

我初學dfs時遇到的第一題應該就是這道吧

本文面向初學者,說的較為詳細

側重於作者的做題過程

我相信很多人都會像我一樣去做

列舉每一行的皇后的位置即可

對角線的處理非常令人迷茫

一開始,我興奮地打了這樣乙個**:

用二維陣列vis標記一下能不能放不就好了嗎?

看題解說的花裡胡哨的……

void dfs(int x)

return;

} for(int i=1;i<=n;i++)

for(int j=1;j<=n;j++)

dfs(x+1);

for(int j=x+1;j<=n;j++)

vis[j][i]=0;

for(int j=1;j<=n;j++)

for(int j=1;j<=n;j++)

} }return;

}

內心無比歡悅!

——然鵝,樣例都沒過

原來會有重疊!回溯的時候改的並不是原來的值,原來已經否認了這種情況。

瞄了眼看起來極小的資料範圍,懶人我怎麼會不偷懶呢。

直接拿個三維陣列viss存一下不就好了,更新還方便,無腦。

一心以為複雜度炸不了的

(我居然算都沒算……)

於是這樣乙份**橫空出世……

void dfs(int x)

return;

} for(int i=1;i<=n;i++)

for(int j=1;j<=n;j++)

dfs(x+1);

for(int j=1;j<=n;j++)

for(int k=1;k<=n;k++)

vis[j][k]=viss[x][j][k];

} }return;

}

於是tle87分滾粗

q:那就只儲存要更新的不就行了嗎?這樣時間複雜度不會炸的呀

a:試過了,我好像打錯了。您可以自己試一試。

此時我發現我一道經典題打了這麼久內心已經很崩潰了

(如果在noipcsp考場上我就已經87分滾粗了,所以要注意資料範圍啊)

仔細看題面和原來的思路,

1.我發現一行不會有兩個皇后,所以這是不用存的

2.列用一維陣列vis儲存即可

3.對角線應該怎麼存?

觀察題目提供的圖

向左下角的一條對角線上的格仔行與列的和相等,

向右下角的一條對角線上的格仔行與列的差相等

妙啊,解決了解決了。

to_left[i]表示行與列和為i的格仔所在的向左下角的對角線上是否已有皇后

to_right[i]表示行與列差為i的格仔所在的右下角的對角線上是否已有皇后

且慢——萬一行與列的差為負值怎麼辦

+個n讓它變成正數不就好了……

to_right[i+n]表示行與列差為i的格仔所在的右下角的對角線上是否已有皇后

行與列差最大為n-1,行與列和最大為2*n

這樣我們就知道這兩個陣列要開多大了

ac**

#include using namespace std;

bool vis[15],to_left[30],to_right[30];

//向左的同一條對角線上和相等,向右的差相等

int n,ans[15],cnt;

void dfs(int x)

return;

} for(int i=1;i<=n;i++)

} return;

}int main() {

cin>>n;

dfs(1);

cout

搜尋 P1219 八皇后

檢查乙個如下的6 x 6的跳棋棋盤,有六個棋子被放置在棋盤上,使得每行 每列有且只有乙個,每條對角線 包括兩條主對角線的所有平行線 上至多有乙個棋子。上面的布局可以用序列2 4 6 1 3 5來描述,第i個數字表示在第i行的相應位置有乙個棋子,如下 行號 1 2 3 4 5 6 列號 2 4 6 1...

洛谷 P1219 八皇后

題目描述 檢查乙個如下的6 x 6的跳棋棋盤,有六個棋子被放置在棋盤上,使得每行 每列有且只有乙個,每條對角線 包括兩條主對角線的所有平行線 上至多有乙個棋子。上面的布局可以用序列2 4 6 1 3 5來描述,第i個數字表示在第i行的相應位置有乙個棋子,如下 行號 1 2 3 4 5 6 列號 2 ...

洛谷 P1219 八皇后

題目描述 檢查乙個如下的6 x 6的跳棋棋盤,有六個棋子被放置在棋盤上,使得每行 每列有且只有乙個,每條對角線 包括兩條主對角線的所有平行線 上至多有乙個棋子。上面的布局可以用序列2 4 6 1 3 5來描述,第i個數字表示在第i行的相應位置有乙個棋子,如下 行號 1 2 3 4 5 6 列號 2 ...