寫在前面:
第一次認真寫題解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 ...