狀態壓縮DP 炮兵陣地

2021-09-24 13:06:13 字數 2313 閱讀 9442

這道題真的毒瘤…

首先觀察到列的範圍很小,這啟示我們使用狀態壓縮演算法。

我們可以預處理出所有橫排不互相攻擊的數字,顯然這些數只有一百來個。用b陣列儲存。

我們觀察到一行是否可以防止炮兵和上兩行來決定,我們設f[i

][j]

[k]f[i][j][k]

f[i][j

][k]

表示第i

ii行的狀態為b

jb_j

bj​,第i−1

i-1i−

1行狀態為b

kb_k

bk​可以放置的最多炮兵。

因此我們設令乙個狀態為l,有乙個顯然的狀態轉移方程是:f[i

][j]

[k]=

max(

f[i]

[j][

k],f

[i−1

][k]

[l]+

coun

t(j)

)f[i][j][k]=max(f[i][j][k],f[i-1][k][l]+count(j))

f[i][j

][k]

=max

(f[i

][j]

[k],

f[i−

1][k

][l]

+cou

nt(j

))此時,我們需要考慮這個狀態轉移方程的限制條件:

**如下:

#include

using

namespace std;

const

int n =

200;

int n, m, ans =

0, s =0;

int a[n]

, f[n]

[n][n]

, b[n]

, c[n]

;bool

check

(int x)

;for

(int i=m-

1;i>=0;

--i)

t[i+1]

= x >> i &1;

for(

int i=

3;i<=m;

++i)

if(t[i]

+t[i-1]

+t[i-2]

>1)

return0;

return1;

}bool

valid

(int x,

int y)

bool

safe

(int x,

int y,

int z)

intcount

(int x)

intmain

(void

) a[i]

= s;

}for

(int i=

0;i<

1<

++i)if(

check

(i)) b[

++s]

= i, c[s]

=count

(i);

memset

(f,-30,

sizeof f)

; f[0]

[1][

1]=0

;for

(int i=

1;i<=n;

++i)

for(

int j=

1;j<=s;

++j)if(

valid

(b[j]

,i))

for(

int k=

1;k<=s;

++k)if(

valid

(b[k]

,i-1)&&

(b[j]

&b[k])==

0)for(

int l=

1;l<=s;

++l)if(

(b[j]

&b[l])==

0) f[i]

[j][k]

=max

(f[i]

[j][k]

,f[i-1]

[k][l]

+c[j]

), ans =

max(ans,f[i]

[j][k]);

cout << ans << endl;

return0;

}

狀態壓縮DP 炮兵陣地

炮兵陣地 time limit 2000ms memory limit 65536k total submissions 11280 accepted 4065 description 司令部的將軍們打算在n m的網格地圖上部署他們的炮兵部隊。乙個n m的地圖由n行m列組成,地圖的每一格可能是山地 ...

炮兵陣地 狀態壓縮DP

一道的經典的狀態壓縮題。司令部的將軍們打算在nm的網格地圖上部署他們的炮兵部隊。乙個nm的地圖由n行m列組成,地圖的每一格可能是山地 用 h 表示 也可能是平原 用 p 表示 如下圖。在每一格平原地形上最多可以布置一支炮兵部隊 山地上不能夠部署炮兵部隊 一支炮兵部隊在地圖上的攻擊範圍如圖中黑色區域所...

狀態壓縮dp 炮兵陣地

題面 司令部的將軍們打算在n m的網格地圖上部署他們的炮兵部隊。乙個n m的地圖由n行m列組成,地圖的每一格可能是山地 用 h 表示 也可能是平原 用 p 表示 如下圖。在每一格平原地形上最多可以布置一支炮兵部隊 山地上不能夠部署炮兵部隊 一支炮兵部隊在地圖上的攻擊範圍如圖中黑色區域所示 如果在地圖...