洛谷P1896 互不侵犯 狀壓dp

2021-09-30 21:06:14 字數 2804 閱讀 6401

在n×n

n×nn×

n的棋盤裡面放k

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

88個格仔。(

n<=9

,k

<=n

∗n

)(n<=9,k<=n*n)

(n<=9

,k<=n

∗n)首先暴搜肯定被否定,時間複雜度是指數級的,所以我們就可用上狀態壓縮dpdp

dp啦。那什麼是狀態壓縮?在這題中按照我的理解就是將一行的所有擺放狀態看成不同的01

0101

,然後將這些01

0101

串看成二進位制數,這樣每乙個擺放狀態就有乙個01

串01串

01串(二進位制數)與其對應。

假設1

11行有4

44個格仔,我們在第1、3

1、31、

3個格仔放棋子,2、4

2、42、

4不放棋子,然後我們定義乙個01

0101

串′ 1′

'1'′1

′表示此處有棋子,′0′

'0'′0

′表示沒有棋子,那麼這個01

0101

串就是1010

1010

1010

。那麼這樣子做有什麼好處?我的答案是操作起來十分方便和節省空間。為什麼方便?因為二進位制下對於這些狀態運用位運算十分好操作。

對於這題我們如何操作?我們可以先預處理第一行的所有可行狀態以及可行狀態can

[i

]can[i]

can[i]

所需的棋子數num

[i

]num[i]

num[i]

,然後根據題目所給條件一直往下遞推。

轉移方程:dp[

i][j

][l]

+=dp

[i−1

][p]

[l−n

um[j

]]

dp[i][j][l]+=dp[i-1][p][l-num[j]]

dp[i][

j][l

]+=d

p[i−

1][p

][l−

num[

j]]。

其中i

ii是當前行,j

jj是當前狀態,p

pp是上一行的可行狀態,l

ll是當前狀態所需的棋子數,所以l

ll從l−n

um[j

]l-num[j]

l−num[

j]而來。如何判斷題目所給的8

88個方向上是否有衝突?因為我們是從上往下遞推,所以在考慮當前行時僅用考慮此格仔的上下左右和左上右上,不需要考慮左下右下。

我們同樣可以預處理一行中的所有狀態,將相鄰的狀態全部否定,那麼我們在遞推的時候就不用考慮這些狀態了。考慮位運算。

假設上一行狀態y

yy,本行狀態xxx。

同行的判斷:如果乙個二進位制數x

xx有相鄰的1

11(棋子),那麼 (

x<

<1)

&x

(x<<1)\&x

(x<

<1)

&x必定不等於000。

左上右上的判斷:我們直接讓x

xx左移或右移一位再&

\&&上y

yy如果不等於0

00則衝突。((x

<

<1)

&y

)((x<<1)\&y)

((x<

<1)

&y)!=0

!=0!=

0,((

x>

>1)

&y

)((x>>1)\&y)

((x>

>1)

&y)!=0

!=0!=

0。正上方的判斷:(x&

y)

(x\&y)

(x&y)!=0

!=0!=

0遞推完後,我們加上最後一行擺放有k

kk個子的狀態的方案數就好了。

知道了這些這題就很簡單 了。

#include

using

namespace std;

typedef

long

long ll;

int n, k, maxsta;

ll ans, num[

1<<10]

, dp[10]

[1<<10]

[10*10

];bool can[

1<<10]

;int

main()

}}for(

int i =

0; i < maxsta; i++)if

(can[i]

&& num[i]

<= k)

dp[1]

[i][num[i]]=

1;//預處理第一行

for(

int i =

2; i <= n; i++)}

}}for(

int i =

0; i < maxsta; i++

) ans +

= dp[n]

[i][k]

; cout << ans <<

'\n'

;return0;

}

蒟蒻的第一題狀壓dpdp

dp,不容易啊。

P1896 互不侵犯 狀壓DP

目錄題目 分析變數定義 剔除左右相鄰的狀態 計算king state 如何動態規劃?如何表示限制條件 原博主的 寫在最後 在n n的棋盤裡面放k個國王,使他們互不攻擊,共有多少種擺放方案。國王能攻擊到它上下左右,以及左上左下右上右下八個方向上附近的各乙個格仔,共8個格仔。輸入格式 只有一行,包含兩個...

互不侵犯(洛谷P1896)

題目 在n n的棋盤裡面放k個國王,使他們互不攻擊,共有多少種擺放方案。國王能攻擊到它上下左右,以及左上左下右上右下八個方向上附近的各乙個格仔,共8個格仔。輸入輸出 輸入n,k,輸出有幾種放置方法。n 9,k n 2 樣例輸入輸出 入 3 2 出 16 這道題看範圍就顯然是狀壓dp了吧。其實這道題和...

洛谷 1896 互不侵犯

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