浅谈状压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]);
}