最近被狀態壓縮dp虐得不行,今天終於決定正視自己的弱項,好好把dp練習一下,把今天做的幾道狀態壓縮dp總結一下,一定要想辦法擺脫dp弱菜這個標籤!!!
poj 3254 :
應該是最基礎的狀態壓縮dp了吧,設dp[i][flag]表示第i行狀態為flag時的排放總數,預處理一下dp[1][flag],對於dp[i][flag](i>=2),則dp[i][flag]=dp[i][flag]+dp[i-1][pre]當且僅當pre滿足以下幾個條件:
1:flag和pre都不含有相鄰的1(二進位制)
2:flag和pre分別滿足第i行和第i-1行的約束條件。
3:flag和pre在同一位上不能同時為1(二進位制)。
還是挺簡單的,用位運算可以簡單實現。**如下:
#include #include #include #include #define mod 100000000
using namespace std;
vectort;
int check(int x)
}for(i=2;i<=n;i++)}}
}}
for(i=0;i=limit)
break;
ans=(ans+dp[n][i])%mod;
}printf("%i64d\n",ans);
return 0;
}
hdu 4539:
經典的狀態壓縮dp,我們設dp[i][pre][now]表示第i行為now狀態,第i-1行為pre狀態時可以安排的最大士兵數量,這裡的狀態指的是每一行的士兵安排情況,我們把狀態用二進位制表示出來後,第i位為1表示在第i列放置乙個士兵,為0表示不放,因為m<=10所以我們最多只要1024個狀態就可以表示一行的每乙個狀態,事實上這1024個狀態中有大部分是不合法的,(也就是有兩個1其距離為2),所以我們可以預處理出所有的合法狀態,(我們下面所討論的狀態都是合法的)
,對於dp[i][pre][now]我要怎麼計算呢?
首先當然是這兩個狀態不能和所給的矩陣有衝突(也就是在不能人的地方放置了人),然後相鄰兩行不能有距離為2的1存在。滿足上面的條件後,則dp[i][pre][now]=max(dp[i-1][ppre][pre]),其中ppre也要狀態也要滿足以上條件。我們最後求合法狀態中的最大值即可,以上快速判斷是否滿足要求可以用位運算來判斷,具體如何用請自己思考,或者參考我的**。
#include #include #include #include #include using namespace std;
int dp[200][200][200];
vectora[11];
int check(int x,int len)
int num[110];
int main()
num[i]=tmp;
}tmp=a[m].size();
int ans=0;
for(i=0;i>1)&pre)==0)}}
}ans=max(ans,dp[i][s][j]);}}
}}}}
printf("%d\n",ans);
}return 0;
}
poj 1185
和上一道題差不多(連名字都一樣),只是判斷合法狀態的方法不同而已,大部分都是一樣的。只是變了一點形式而已,這裡不多說了。直接看**。
#include #include #include #include #include using namespace std;
int dp[110][65][65];
vectora[11];
int check(int x,int len)
int num[110];
char bo[110][12];
int main()
for(i=1;i<=n;i++)
num[i]=tmp;
}tmp=a[m].size();
int ans=0;
for(i=0;i
poj 2411
一年前就看過了,當時根本就不敢碰,今天終於鼓起勇氣發現並不是很難,沒用long longwa一次,然後2y。
我們設dp[i][flag]表示第i行為狀態flag的排列總數,這裡我們設豎著放為1(上面那一段在第i行),其他為0(為0不一定為橫著放,以為有可能上一行是豎著放的)。我們先預處理第一行的情況,然後對於dp[i][flag],(2<=i
1:flag和pre在同一位上不能同時為1.即(pre&flag==0)
2 : 我們設合法狀態的定義如下:若乙個狀態中相鄰兩個1之間0的個數均為為偶數,則稱它為合法狀態。如長度為4的狀態中1001(9) 1100是合法狀態,而1010 1101不是。(注意對於同乙個狀態,有些長度下是合法的,有些長度下是不合法的,如1001和01001,在長度4下為合法狀態,在長度5下則不是)
則pre^now必須為合法狀態(這裡的^為異或運算)。
注意到我們不用求dp[n][flag],因為若第n-1行確定了,則最後一行也已近確定了,則我們只要計算dp[n-1][flag]中屬於合法狀態的flag,求它們的和即可。若h*w為奇數,之間輸出0即可,否則若h為1,輸出1,不然的話就按上面的方法求。
**如下:其實可以加很多優化的,但人懶就沒加了。。。
#include #include #include #include #include using namespace std;
vectort[12];
int check(int x,int len)
}if((len-l+1)%2)
return 0;
return 1;
}void init()
{ int i,j;
for(i=1;i<=11;i++)
{int tmp=(1<
狀態壓縮DP題目小節(二)
最近做的狀態壓縮dp小節 zoj 4257 一堆氣體相互碰撞產生能量,求最後能產生的最大能量,應該是很基礎的狀態壓縮dp吧,設dp flag 表示狀態flag時能產生的最大能量,flag中1表示該氣體還存在,0表示該氣體已經消失 邊界條件是flag所有位都為一時,這時產生的能量為0,然後就列舉最後剩...
狀態壓縮dp入門題目
題目大意是有m n的玉公尺地,但其中有些是不肥沃的,不能種植。用1來代表肥沃,0代表不肥沃。另外奶牛不喜歡挨著吃,也就是說要間隔著種植,求有幾種種植方式,並將計算結果對1e8取模。include include using namespace std int dp 12 1 12 dp i s 第i...
狀態壓縮DP
首先,我們以一道狀壓經典題tsp來引入。tsp問題 一張圖上有n個點,給定相應的鄰接矩陣,需要求出從0號節點出發,經過且只經過每個頂點一次,最後仍回到0號節點的最小邊權。思路 假設現在已訪問過的頂點集合 起點0當作還未訪問過的頂點 為s,當前所在頂點為v,用dp s v 表示從v出發訪問剩餘的所有頂...