状态压缩DP入门
Posted coder-cjh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了状态压缩DP入门相关的知识,希望对你有一定的参考价值。
简介
状态压缩DP是将一连串状态压缩成为一个P进制(P通常为2)数,并由此达到压缩的目的
例题
P1879 [USACO06NOV]玉米田Corn Fields
因为只和之前的一行有关系,就可以通过状压先找出这一行中合法的状态,再和上一行的进行转移
Code
#include<bits/stdc++.h> using namespace std; const int mod=1e8; int n,m,f[20][5001]; struct stateint c[5005],num;a[20]; void change(int k,int t) for(int i=0;i<(1<<n);i++) if(!(i&(i<<1))&&!(i&(i>>1))&&!(i&t)) a[k].c[++a[k].num]=i; int main() scanf("%d%d",&m,&n); for(int i=1;i<=m;i++) int t=0; for(int j=1,x;j<=n;j++) scanf("%d",&x),t=(t<<1)+1-x; change(i,t); for(int i=1;i<=a[1].num;i++)f[1][i]=1; for(int i=2;i<=m;i++) for(int j=1;j<=a[i].num;j++) for(int k=1;k<=a[i-1].num;k++) if(!(a[i].c[j]&a[i-1].c[k])) f[i][j]=(f[i-1][k]+f[i][j])%mod; int ans=0; for(int i=1;i<=a[m].num;i++) ans=(ans+f[m][i])%mod; printf("%d\n",ans);
这题还要简单一些,不用考虑限制
#include<bits/stdc++.h> using namespace std; int n,k; long long f[15][155][155]; int num[155],s[155]; int main() scanf("%d%d",&n,&k); for(int i=0;i<(1<<n);i++) if(i&(i<<1))continue; s[++s[0]]=i; for(int j=0;j<n;j++)if(i&(1<<j))++num[s[0]]; f[0][1][0]=1; for(int i=1;i<=n;i++) for(int j=1;j<=s[0];j++) for(int kk=0;kk<=k;kk++) if(kk>=num[j]) for(int t=1;t<=s[0];t++) if(!(s[t]&s[j])&&!(s[t]&(s[j]>>1))&&!(s[t]&(s[j]<<1))) f[i][j][kk]+=f[i-1][t][kk-num[j]]; long long ans=0; for(int i=1;i<=s[0];i++)ans+=f[n][i][k]; printf("%lld\n",ans);
以上是关于状态压缩DP入门的主要内容,如果未能解决你的问题,请参考以下文章
DP问题从入门到精通4(状态压缩dp,蒙德里安,最短Hamilton路径)
DP问题从入门到精通4(状态压缩dp,蒙德里安,最短Hamilton路径)