1896 SCOI2005 互不侵犯 狀壓dp

2022-05-16 02:36:08 字數 1275 閱讀 8258

傳送門

這是一道狀壓dp的經典例題

題目讓輸出所有可能的方案數

很顯然 這是一道動態規劃了

由於國王放置的位置有一定的限制 所以我們要在狀態轉移的過程中增加一維來儲存狀態

我們這一道題假設f[i][j][k] 意思是在前i行一共放置了j個國王 第i行國王放置的狀態是k  儲存的值是方案數

首先 我們可以先預處理出左右合法的每行的狀態。。。(有點繞

就是說針對單獨的一行 會有那些合法的狀態 使得相鄰的兩個格仔最多只能放置乙個國王 沒有相鄰的國王

然後我們開始dp

我們分別列舉i k s 

i是當前列舉到第幾行

k是第i行的狀態 編號

s是第i-1行的狀態編號

然後我們還要判斷一下

上下不能相等,對角線不能相等

這些條件都滿足之後 我們就可以列舉第i行國王的個數 並從上一行的狀態累加到當前狀態

最後我們把最後一行 放滿ss個國王 的不同狀態的f陣列的值累加起來就是總的方案數

進行位運算的時候還要注意一點 

就是一定要多加括號!!!

//

p1896 [scoi2005]互不侵犯

#include#define ll long long

using

namespace

std;

int p[300

];int num[300];//

記錄每一種狀態有多少個1

ll f[10][90][300

];int

main()

}

} f[

0][0][1]=1;//

什麼都不放的方案數是1 初始化

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

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

for(int s=1;s<=cnt;s++)

if((p[k]&p[s])==0)//

沒有上下攻擊

if(((p[k]>>1)&p[s])==0

)

if(((p[s]>>1)&p[k])==0

)

long

long ans=0

;

for(int i=1;i<=cnt;i++)

ans+=f[n][ss][i];

cout

return0;

}

P1896 SCOI2005 互不侵犯

p1896 scoi2005 互不侵犯 資料不大,時間複雜度很高也差不多能過。使用狀壓dp dp i j k 表示到第i行,狀態為j,選了k個人 然後就是轉移,轉移的難點就是快速判斷 判斷的話,我們整體考慮。然後乙個狀態是否有相鄰的國王。用它本身按位與它本身右移 左移 若結果為0,則說明無相鄰的國王...

P1896 SCOI2005 互不侵犯

首先,養成乙個思路 資料這麼小?狀壓dp!然後翻題解可以這麼定義狀態 定義 dp i j k 為前 i 行中,第 i 行狀態為 j 前 i 行已放置 k 個國王的方案數。顯然一行的狀態只與前一行的有關,所以只需要記錄一行的狀態。但是一行的狀態好像很難存啊!難道複製乙個陣列進去嗎?其實,對於每乙個點,...

P1896 SCOI2005 互不侵犯

在n n的棋盤裡面放k個國王,使他們互不攻擊,共有多少種擺放方案。國王能攻擊到它上下左右,以及左上左下右上右下八個方向上附近的各乙個格仔,共8個格仔。注 資料有加強 2018 4 25 只有一行,包含兩個數n,k 1 n 9,0 k n n 所得的方案數 輸入樣例 1 複製3 2 輸出樣例 1 複製...