列表

详情


NC19997. [HAOI2016]字符合并

描述

有一个长度为 n 的 01 串,你可以每次将相邻的 k 个字符合并,得到一个新的字符并获得一定分数。得到的新字符和分数由这 k 个字符确定。你需要求出你能获得的最大分数。

输入描述

第一行两个整数n,k。
接下来一行长度为n的01串,表示初始串。
接下来2^k行,每行一个字符ci和一个整数wi,ci 表示长度为k的01串连成二进制后按从小到大顺序得到的第i种合并方案得到的新字符,wi表示对应的第i种方案对应获得的分数。
1 ≤ n ≤ 300,0 ≤ ci ≤ 1,wi ≥ 1, k ≤ 8

输出描述

输出一个整数表示答案

示例1

输入:

3 2
101
1 10
1 10
0 20
1 30

输出:

40

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 206ms, 内存消耗: 186904K, 提交时间: 2022-08-02 22:33:03

#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;
}

C++ 解法, 执行用时: 803ms, 内存消耗: 226084K, 提交时间: 2022-05-28 14:35:17

#include <bits/stdc++.h>
using namespace std;
int n,m,a[310],c[300],w[300];
long long f[310][310][300];
char S[310];
int main()
{
	scanf("%d%d",&n,&m);
	scanf("%s",S+1);
	for (int i=1;i<=n;i++)
	  a[i]=int(S[i]-48);
	for (int i=0;i<(1<<m);i++)
  	  scanf("%d%d",&c[i],&w[i]);
  	memset(f,-10,sizeof(f)); 
  	for (int i=1;i<=n;i++) f[i][i][a[i]]=0; 
  	for (int len=2;len<=n;len++) 
  		for (int l=1;l<=n-len+1;l++) {
		    int r=len+l-1;
		    for (int s=0;s<(1<<m);s++) 
		  	  for (int k=r;k>l;k-=(m-1))
		  	    f[l][r][s]=max(f[l][r][s],f[l][k-1][s>>1]+f[k][r][s&1]);
		    if ((len-1)%(m-1)==0) {
		    	long long g[2];
				g[0]=g[1]=-1e12; 
		  	    for (int s=0;s<(1<<m);s++)
		  	      g[c[s]]=max(g[c[s]],f[l][r][s]+w[s]);
		  		f[l][r][0]=g[0];f[l][r][1]=g[1];
		    }	
		  }
	long long ans=0;
	for (int i=0;i<(1<<m);i++)
	  ans=max(ans,f[1][n][i]);
	cout<<ans;
	return 0;
}

上一题