BZOJ 4565 状压DP
思路:
f[i][j][S]表示从i到j压成S状态
j-m是k-1的倍数
$f[i][j][S<<1]=max(f[i][j][S<<1],f[i][m-1][S]+f[m][j][0]),$
$f[i][j][S<<1|1]=max(f[i][j][S<<1|1],f[i][m-1][S]+f[m][j][1]);$
为了区分001 01 和1
更新的时候要新开一个数组记录 最后再更新
//By SiriusRen #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define int long long int n,k,f[333][333][256],g[2],ans,c[333],w[333]; char s[333]; signed main(){ scanf("%lld%lld",&n,&k); scanf("%s",s+1); for(int i=0;i<(1<<k);i++)scanf("%lld%lld",&c[i],&w[i]); memset(f,0xcf,sizeof(f)); for(int i=1;i<=n;i++)s[i]-='0',f[i][i][s[i]]=0; for(int l=2;l<=n;l++) for(int i=1;i<=n-l+1;i++){ int j=i+l-1,len=j-i; while(len>=k)len-=k-1; for(int m=j;m>i;m-=k-1) for(int S=0;S<(1<<len);S++) f[i][j][S<<1]=max(f[i][j][S<<1],f[i][m-1][S]+f[m][j][0]), f[i][j][S<<1|1]=max(f[i][j][S<<1|1],f[i][m-1][S]+f[m][j][1]); if(len==k-1){ g[0]=g[1]=-100000000000000ll; for(int S=0;S<(1<<k);S++) g[c[S]]=max(g[c[S]],f[i][j][S]+w[S]); f[i][j][0]=g[0],f[i][j][1]=g[1]; } } for(int i=0;i<(1<<k);i++)ans=max(ans,f[1][n][i]); printf("%lld\n",ans); }