思路
可能是个套路题,但是没见过...
第一眼觉得是个区间,但是中间的状态总是弄不清楚...
然后看了题解是状压+区间.
令表示为区间
合并成字符串
所获得的最大代价.
区间的划分有个优化就是,每次只能是
这种才能形成
,然后就行划分,当区间是这个长度的时候进行一次答案统计即可.
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=3e2+5,M=(1<<8);
char s[N];
ll w[M],c[M],g[2];
ll f[N][N][M];//从l到r合并成v的最大价值是多少.
int main()
{
int n,k;
scanf("%d%d",&n,&k);
scanf("%s",s+1);
for(int i=0;i<(1<<k);i++)
scanf("%lld%lld",&c[i],&w[i]);
memset(f,-0x3f,sizeof f);
ll inf=-(0x3f3f3f3f);
for(int i=1;i<=n;i++) f[i][i][s[i]-'0']=0;
for(int len=2;len<=n;len++)
{
for(int l=1;l<=n-len+1;l++)
{
int r=l+len-1;
int x=(len-1)%(k-1);
if(x==0) x=k-1;
for(int mid=r-1;mid>=l;mid-=(k-1))
{
for(int s=0;s<(1<<x);s++)
{
f[l][r][s<<1]=max(f[l][r][s<<1],f[l][mid][s]+f[mid+1][r][0]);
f[l][r][s<<1|1]=max(f[l][r][s<<1|1],f[l][mid][s]+f[mid+1][r][1]);
}
}
if(x==k-1)
{
g[0]=g[1]=inf;
for(int i=0;i<(1<<k);i++) g[c[i]]=max(g[c[i]],f[l][r][i]+w[i]);
f[l][r][0]=g[0],f[l][r][1]=g[1];
}
}
}
ll ans=inf;
for(int i=0;i<(1<<k);i++)
ans=max(ans,f[1][n][i]);
printf("%lld\n",ans);
return 0;
}

京公网安备 11010502036488号