狀態壓縮dp總結 長期更新

2021-08-04 03:43:01 字數 1771 閱讀 3608

狀壓dp本人做的題目真的不太多...至今還未理解到其中的精髓.所以以下的思路

描述中有存在不當的地方希望能夠指出.另外,有些地方說的比較複雜,因為本弱雞

對這些東西不是很理解.....多寫點有助於理解吧.

poj 1185  經典狀壓dp     

我隊友這篇博文還不錯.

思路:

首先,我們可以發現對於每一行的當前位置能不能放炮兵,只與他的上一行和上上一行

的炮兵位置有關係,所以要開乙個三維陣列轉移關係.

0表示不放大炮,1表示放大炮,同樣的,先要滿足硬體條件,即有的地方不能放大炮,

然後就是每一行中不能有兩個1的距離小於2(保證橫著不互相攻擊),這些要預先處理一下。然後就是

狀態表示和轉移的問題了,因為是和前兩行的狀態有關,所以要開個三維的陣列來表示狀態,當前行

的狀態可由前兩行的狀態轉移而來。即如果當前行的狀態符合前兩行的約束條件(不和前兩行的大炮

互相攻擊),則當前行的最大值就是上乙個狀態的值加上當前狀態中1的個數(當前行放大炮的個數) 

【狀態表示】dp[i][j][k] 表示第i行為第j個狀態,第i-1為第k個狀態時的最大炮兵個數。 

【狀態轉移方程】 dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][t]+num[j]);//num[j]為第j個狀態中的二進位制1的個數

【dp邊界條件】dp[1][i][0] =num[i] 狀態i能夠滿足第一行的硬體條件

(注意:這裡的i指的是第i個狀態,不是乙個二進位制數,開乙個陣列儲存二進位制狀態) 

思考:對於這種有地形限制的,標記乙個點其他周圍都有影響的,一般都要預處理.將所有可能的狀態

和地形的限制預處理出來,

每次列舉第i個狀態的時候,要首先滿足地形的限制,在滿足各行各列之間

的關係.

#include#include#include#includeusing namespace std;

const int maxn=111;

int dp[maxn][maxn][maxn];//dp[i][j][k] 第i行為第j個狀態,第i-1行為第k個狀態時的最大炮兵數

int status[maxn],num[maxn]; //status[i] 當前第i個狀態的二進位制 kk(1放大炮 0 不放).

//num[i]存放與status相對應的當前的第i個狀態的二進位制中有多少個1,即放了多少炮兵

char s[maxn];

int mp[maxn];//存放地形的限制,1表示不能放大炮,0表示可以放大炮.

int n,m;

int _count(int x)

return __;

}int main()

return _;

}int check_row(int r,int i)//判斷第r行的第i個狀態和r的地形是否衝突

int check_sta(int i,int j)//判斷第i個狀態和第j個狀態是否衝突。

int main()

{ scanf("%d",&t);

while(t--)

{memset(dp,0,sizeof(dp));

memset(mp,0,sizeof(mp));

memset(status,0,sizeof(status));

memset(num,0,sizeof(num));

scanf("%d %d",&n,&m);

for(int i=1;i<=n;i++)

{int x;

for(int j=0;j

狀態壓縮DP總結

參考部落格 狀態壓縮主要指的是用位運算代替列舉壓縮dp的時間,如果某乙個狀態和之前狀態的順序沒有關係,那麼就可以將之前的選或者不選壓縮到乙個二進位制數中。在選擇第i個時列舉之前的所有可能的i 1狀態,但是這i 1狀態是不記錄順序的,只在i 1到i時考慮順序,這樣的話往往能夠節約很多時間。大致題意是從...

狀壓dp(總結)狀態壓縮

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

狀態壓縮DP

首先,我們以一道狀壓經典題tsp來引入。tsp問題 一張圖上有n個點,給定相應的鄰接矩陣,需要求出從0號節點出發,經過且只經過每個頂點一次,最後仍回到0號節點的最小邊權。思路 假設現在已訪問過的頂點集合 起點0當作還未訪問過的頂點 為s,當前所在頂點為v,用dp s v 表示從v出發訪問剩餘的所有頂...