1. 程式人生 > 實用技巧 >淺談狀壓DP

淺談狀壓DP

淺談狀壓DP

狀壓DP,是指通過一個01串來記錄轉移的狀態,再通過DP的思想轉移方程。

例:如共有五個節點,當前選擇了第1、2、3號節點,則狀態為

(00111)2 = (7) 10

由於計算機中的儲存都採用二進位制,我們可以通過位運算很方便的進行狀態轉移

注意:狀壓DP一般資料範圍較小,多通過位運算進行轉移,且較為簡單。但一般需要預處理,需要十分細緻,很鍛鍊碼力。

例:JDOJ P1104 最佳挑水

題目傳送門

一道狀壓DP裸題,我的做法是預處理出所有挑水方式的狀態,並將矩陣存為DP陣列的初始值。

#include<cstdio>
#include<cstring>
int n;
int dp[1<<19];
int sta[400],cnt=0;
int min(int x,int y)
{
return x<y?x:y;
}
int main()
{
scanf("%d",&n);
memset(dp,0x3f,sizeof(dp));
for(int i=0;i<n;i++)
{
int l = 1 << i ;
for(int j=0;j<n;j++)
{
int r = 1 << j;
int v;
scanf("%d",&v);
if(j==i) continue;
sta[++cnt] = l + r;
dp[l|r] = v ;
}
}
dp[0] = 0;
for(int i=1;i<=cnt;i++)
{
int s = sta[i];
for(int j=0;j<=(1<<n)-1;j++)
{
if((s&j)==0)
{
dp[s|j] = min(dp[s|j],dp[s]+dp[j]);
}
}
}
printf("%d",dp[(1<<n)-1]);
}