狀壓DP bzoj1087 互不侵犯king

2022-05-28 15:51:08 字數 1241 閱讀 7964

在n×n的棋盤裡面放k個國王,使他們互不攻擊,共有多少種擺放方案。國王能攻擊到它上、下、左、右,以及左上、左下、右上、右下八個方向上附近的各乙個格仔,共8個格仔。

只有一行,包含兩個數n,k ( 1 <=n <=9, 0 <= k <= n * n)

方案數3 2

原題鏈結→_→bzoj1087: [scoi2005]互不侵犯king

其實我們可以用一張美妙的表來解決這道題(劃掉)這道題我們首先考慮暴搜解決,然而似乎狀態略多會炸……

對於每一行的狀態,我們用1表示國王,0表示不放國王。由於每個位置只有0和1兩種狀態,我們可以使用位運算判斷每行的狀態是否合法。例如:10101010就是一種合法狀態,而11111111就不合法。每行狀態表示的十進位制數就是我們壓縮後的狀態。

我們需要做兩個預處理,先列舉每行所有可能的狀態,記錄下合法狀態。然後判斷兩個狀態是否能作為臨行放置,並用布林型別的二維陣列儲存其關係。

預處理之後,就是常規的dp,狀態轉移方程如下:

f[i][j][now]=∑f[i-1][j-num[now]][q]

略作說明:f[i][j][k]代表前i行,總共放j個國王,第i行狀態為k時的方案數。狀態轉移方程中的num[now]代表狀態為now的行中國王的數目,q表示第i-1行的狀態。

1 #include2

intn,k;

3long

long

ans;

4bool s[600],map[600][600];//

判斷狀態是否合法;判斷兩個狀態是否能作為臨行

5int num[600];//

num[i]代表編號為i的狀態含有的國王數

6long

long f[10][100][600];7

intsum;

8void pre_s()//

預處理s陣列

922 num[i]=cnt;

23 f[1][cnt][i]=1;24

}25}26

}27void pre_map()//

預處理map陣列

2838}39

}40void

dp()

4157}58

}59intmain()

6071 printf("

%lld

",ans);

72return0;

73 }

bzoj1087 互不侵犯king

BZOJ 1087 互不侵犯King(狀壓DP)

time limit 10 sec memory limit 162 mb submit 3984 solved 2323 submit status discuss 在n n的棋盤裡面放k個國王,使他們互不攻擊,共有多少種擺放方案。國王能攻擊到它上下左右,以及左上 左下右上右下八個方向上附近的各乙...

BZOJ 1087 互不侵犯King (狀壓dp)

time limit 10 sec memory limit 162 mb description 在n n的棋盤裡面放k個國王,使他們互不攻擊,共有多少種擺放方案。國王能攻擊到它上下左右,以及左上 左下右上右下八個方向上附近的各乙個格仔,共8個格仔。input 只有一行,包含兩個數n,k 1 n ...

BZOJ1087 互不侵犯king(狀壓DP)

題目大意 在n n 1 n 9 的棋盤裡面放k個國王,使他們互不攻擊,共有多少種擺放方案。國王能攻擊到它上下左右,以及左上左下右上右下八個方向上附近的各乙個格仔,共8個格仔 題解 看n的範圍1 n 9,大概就是狀壓dp了。把行的放法壓起來,狀態還是比較好想的。f i j now 表示前i行一共放了j...