您的位置:首页 > 其它

4565: [Haoi2016]字符合并 区间DP

2016-05-21 23:43 246 查看
令fi,j,k表示区间[i,j]合并成k的最大收益,其中K=0/1保证[i,j]可以合并成一个数。

转移的时候用gj,k表示对于当前的i,[i,j]合并成了k,其中k是一个二进制数。

然后转移一下就行了

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

const int N=305;
int n,m;
int a
,c
,w
;
long long f

[2],g

,tmp[2],ans
;
char s
;

inline int read()
{
int a=0,f=1; char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
return a*f;
}

int main()
{
n=read(); m=read();
memset(f,-1,sizeof(f));
scanf("%s",s+1);
for (int i=1;i<=n;i++) f[i][i][s[i]-'0']=0;
for (int i=0;i<1<<m;i++)
c[i]=read(),w[i]=read();
for (int i=n-m+1;i;i--)
{
memset(g,-1,sizeof(g));
int now=1;
g[i][0]=f[i][i][0];
g[i][1]=f[i][i][1];
for (int j=i+1;j<=n;j++)
{
for (int s=0;s<1<<now;s++)
if (g[j-1][s]>=0)
for (int k=j;k<=n;k+=m-1)
{
if (f[j][k][0]>=0)
g[k][s<<1]=max(g[k][s<<1],g[j-1][s]+f[j][k][0]);
if (f[j][k][1]>=0)
g[k][s<<1|1]=max(g[k][s<<1|1],g[j-1][s]+f[j][k][1]);
}
if (++now==m)
{
memset(tmp,-1,sizeof(tmp));
for (int s=0;s<1<<m;s++)
if (g[j][s]>=0)
tmp[c[s]]=max(tmp[c[s]],w[s]+g[j][s]);
f[i][j][0]=g[j][0]=tmp[0];
f[i][j][1]=g[j][1]=tmp[1];
now=1;
}
}
}
for (int i=1;i<=n;i++)
for (int j=i;j<=n;j+=m-1)
ans[j]=max(ans[j],ans[i-1]+max(f[i][j][0],f[i][j][1]));
cout << ans
<< endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: