dp亂寫1 狀態壓縮dp(狀壓dp)炮兵陣地

2022-05-30 18:00:15 字數 3247 閱讀 9139

題意:炮兵在地圖上的擺放位子只能在平地('p')

炮兵可以攻擊上下左右各兩格的格仔;

而高原('h')上炮兵能夠攻擊到但是不能擺放

求最多能擺放的炮兵的數量

就是這個意思。

難度提高,弱省省選

一開始是想寫dfs(迷之八皇后)的,

但是看到資料量100就想dp了;

因為題目n的範圍給的很少n<=10,想到狀壓

非常明顯是乙個狀態壓縮的dp(狀壓dp)

其實可以當做狀壓的入門題目來做。

由於本行的狀態是由前若干行推出來的,所以想到了從上推到下(而不是從左推到右)

還有,本行的狀態與前1行,前2行的狀態密切相關的(炮兵不互相攻擊)

寫出我們dp的狀態:f[i,r1j]表示當前第i行狀態為j,i-1行狀態為r1的炮兵數

轉移其實就是非常簡單了:(r2就是前第2行的狀態)

f[i,r1,j]:=max(f[i,r1,j],f[i-1,r2,r1]+sum[j]);

轉移的條件:r1和r2不與h有乙個重合;r1和r2不能被互相打到或達j

本題主要難在處理dp初始化的方面;

首先我們需要保證每一種拓展出來的炮兵排列的方式需要在該行中橫向不互相攻擊;

這種每行不攻擊的序列總數小於等於60;

pd函式非常好寫:

function pd(x:longint):boolean;//

判斷此時放的是否合法(附近兩位不能有1)

begin

if (x and (x<<1))<>0 then exit(false);

if (x and (x<<2))<>0 then exit(false

);exit(

true

);end;

引入col[i]的二進位制陣列,表示第i行『h』的分布 if s[j]='h' then col[i]:=col[i] or (1<<(j-1));

注意這裡需要j-1,因為二進位制是從2^0開始的。

注意初始化第0行所有地點都是高山,由於第0行可能會影響第2行;

特殊處理第一行:(st陣列儲存所有合法的序列,cnt為合法序列的個數,st標號1~cnt)

for i:=1 to cnt do

begin

if (col[1] and st[i])=0 then f[1,1,i]:=sum[i];

end;

所以,本題的**簡單,主要注意的是初始值和dp式不要寫錯(4維的轉移,暴力)

uses math;

varn,m,i,j,r1,r2,ans,cnt:longint;

f:array[

0..100,0..100,0..100

]of longint;

//f[i,j,k]表示當前第i行狀態為j,i-1行狀態為k的炮兵數

s:string

; st,sum,col:array[

0..100

]of longint;

function pd(x:longint):boolean;

//判斷此時放的是否合法(附近兩位不能有1)

begin

if (x and (x<<1))<>0 then exit(false);

if (x and (x<<2))<>0 then exit(false

); exit(

true

);end;

function getbit(x:longint):longint;

//求出二進位制數x中有幾個1

varsum:longint;

begin

sum:=0;

while x>0

dobegin

if (x and 1)=1

then inc(sum);

x:=x>>1

; end;

exit(sum);

end;

procedure getdp(m:longint);

vare,i:longint;

begin

e:=1

for i:=0 to e-1

doif

pd(i) then begin

inc(cnt);

st[cnt]:=i; //

儲存此時的狀態

sum[cnt]:=getbit(i); //

炮兵的個數

end;

end;

begin

readln(n,m);

getdp(m);

fillchar(col,

sizeof(col),0);

for i:=1 to m do col[0]:=col[0] or (1

begin

readln(s);

for j:=1 to m do

if s[j]='

h' then col[i]:=col[i] or (1

<<(j-1

)); end; //

col[i]表示第i行高地的分布

fillchar(f,sizeof(f),255);//

clear!

for i:=1 to cnt do

begin

if (col[1] and st[i])=0 then f[1,1,i]:=sum[i];

end;

for i:=2 to n do

for j:=1 to cnt do

//現在這行的狀態是j

if (col[i] and st[j])=0

then

for r1:=1 to cnt do

//上一行狀態是r1

if (st[j] and st[r1])=0

then

for r2:=1 to cnt do

//上上行的狀態是r2

if (st[j] and st[r2])=0

then

if f[i-1,r2,r1]<>-1

then

f[i,r1,j]:=max(f[i,r1,j],f[i-1,r2,r1]+sum[j]);

ans:=0;

for i:=1 to cnt do

for j:=1 to cnt do

ans:=max(ans,f[n,i,j]);

writeln(ans);

end.

狀壓dp(總結)狀態壓縮

狀壓這個和二進位制分不開關係 所以,對於二進位制的熟悉是必不可少的技能 與操作,1不變,0變0 或操作,0不變,1變1 異或操作,0不變,1取反 取反操作,把每乙個二進位制位0變1,1變0 還有一些複雜操作可以根據這些去理解 狀態壓縮 所謂狀態壓縮就是把dp的每一次轉移時的狀態用二進位制來表示 或者...

狀態壓縮動態規劃(狀壓DP)

狀態壓縮動態規劃就是我們常說的狀壓dp,前兩天某廠實習生二面面試官隨手就給我抽了一道狀壓dp的題,我根本沒思路,sorry就寫了一行注釋。然後leetcode周賽最後一題又碰到了狀壓dp的題目,我一定要搞定這個型別的問題。加油加油 狀壓dp說簡單也簡單,基本上就是用一串二進位制樹來表示當前情況 的狀...

狀壓dp 玉公尺田 狀壓dp

相關 強相關 327.玉公尺田 狀壓dp 小國王 狀壓dp 是井字形,本題是十字形。思路 狀態計算 時間複雜度 n 2 n 2n o n 22n 12 2 24n 2 n 2 n o n2 12 2 n 2n 2 n o n22n 12 224 看著妥妥超時,但是裡面合法狀態很少 依舊可以過 在此,...