狀壓dp SCOI 2005 互不侵犯

2021-08-26 02:42:59 字數 3047 閱讀 7104

題意:在n×n

n×nn×

n的棋盤裡面放k

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

88個格仔。

考慮如何狀壓,對於每一行,我們用乙個長度為n

nn的二進位制串表示每一行的狀態,比如1010

1010

1010

表示第乙個,第三個位置上有國王,而1010

1010

1010

對應的十進位制數為10

1010

,我們將每一行的狀態都用二進位制表示然後狀壓成乙個十進位制數。一共有2n−

12^-1

2n−1

種狀態,因為最多的就是一行全為1

11的情況。

接下來設計狀態:dp[

i][j

][k]

dp[i][j][k]

dp[i][

j][k

]表示第i

ii行的狀態為j

jj(j

jj即為狀壓後的十進位制數),前i

ii行一共使用了k

kk個國王。這裡定義num

[i

]num[i]

num[i]

表示一行狀態為i

ii時的國王個數,k

kk為當前這一行的狀態,j

jj為上一行的狀態,q

qq為到前一行總共放的國王個數。所以:dp[

i][k

][q+

num[

k]]+

=dp[

i−1]

[j][

q]

;dp[i][k][q+num[k]]+=dp[i-1][j][q];

dp[i][

k][q

+num

[k]]

+=dp

[i−1

][j]

[q];

首先我們先預處理出對於一行內哪些狀態是合法的,如果狀態i

ii合法即記boo

k[i]

=1

book[i]=1

book[i

]=1,對於每一種合法狀態,我們處理出合法這種狀態需要的國王個數num

[i

]num[i]

num[i]

。對於同一行,乙個國王不能有左右相鄰的國王,所以對於狀態i

ii,我們讓i

ii&(

i>

>1)

,i

(i>>1),i

(i>

>1)

,i&(

i<

<1)

(i<<1)

(i<

<1)

如果二者都為0

00,即為合法。對於乙個合法狀態i

ii,我們對它進行二進位制分解,求出其中有多少個1

11,即為num

[i

]num[i]

num[i]

,然後設出初始狀態f[1

][x]

[num

[x]]

=1

f[1][x][num[x]]=1

f[1][x

][nu

m[x]

]=1。

for

(ll i=

0;i<(1

<;++i)

if(book[i]

) dp[1]

[i][num[i]]=

1;}

接下來我們分別列舉每一行i

ii,前一行的狀態j

jj,如果前一行的狀態合法,就繼續列舉當前行的所有狀態k

kk,對於當前行的所有狀態,我們首先判斷它是否合法,然後讓前一行的狀態分別&k,(

k<

<1)

,(

k>

>1)

k,(k<<1),(k>>1)

k,(k

<

<1)

,(k>

>1)

,如果均為0

00即視為合法,列舉到前一行總共放的國王個數根據方程進行累加轉移。

最後列舉最後一行的所有狀態累加一下答案即可。

#include

#define ll long long

using namespace std;

ll dp[20]

[1000][

100]

,num[

1000];

bool book[

1000];

ll n,king,ans;

intmain()

if(book[i]

) dp[1]

[i][num[i]]=

1;}for

(ll i=

2;i<=n;

++i)

for(ll j=

0;j<(1

<;++j)

if(book[j]

)for

(ll k=

0;k<(1

<;++k)

if(book[k]&&!

(k&j)&&!

((k<<1)

&j)&&!(

(k>>1)

&j))

for(ll q=num[j]

;q+num[k]

<=king;

++q)

dp[i]

[k][q+num[k]]+

=dp[i-1]

[j][q]

;for

(ll i=

0;i<(1

<;++i)

ans+

=dp[n]

[i][king]

; cout

}

SCOI2005 互不侵犯(狀壓DP)

題意 給定乙個n n的棋盤,放置k個國王,使他們互相攻擊不到對方,共有多少種方案。國王可以攻擊上下左右,左上左下,右上右下附近的一格,共8格。資料範圍 1 n 9,0 k n n.因為n的範圍很小,而且每一行對應的乙個方案可以用乙個二進位制數表示,所以容易想到用狀壓dp。又因題目有限制要用多少個國王...

SCOI2005 互不侵犯(狀壓DP)

在 n n 的棋盤裡面放 k 個國王,使他們互不攻擊,共有多少種擺放方案。國王能攻擊到它上下左右,以及左上左下右上右下八個方向上附近的各乙個格仔,共8個格仔。一行 n,k 方案數狀態壓縮dp基礎 狀壓和二進位制有著不可割捨的聯絡 一幫情況下,我 習慣把狀態抽象成一維 並且用二進位制表示,然後再去想怎...

SCOI2005 互不侵犯 (狀壓DP)

題目鏈結 在 n times n 的棋盤裡面放 k 個國王,使他們互不攻擊,共有多少種擺放方案。國王能攻擊到它上下左右,以及左上左下右上右下八個方向上附近的各乙個格仔,共 8 個格仔。1 le n le 9,0 le k le n n f i,j,l 來表示前 i 行,當前狀態為 j 且已經放置 l...