[HAOI2016] 字符合并

给定一个长度为 (n)(01) 串,每次可以将相邻的 (k) 个字符合并,得到一个新的字符并获得一定的分数。求所能获得的最大分数。

(n leq 300, k leq 8)

Solution

显然长为 (l) 的一段可以合并成长为 ((l-1)mod 7 +1) 的一段

(f[l][r][s]) 表示将 ([l,r]) 合并成状态 (s) 的最大分数,考虑转移,枚举哪一部分合成了最后一位,很显然这部分的长度一定是 (7k+1) 的形式

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 305;
int n,k,s[N],c[N],w[N],f[N][N][N];

signed main() {
    ios::sync_with_stdio(false);
    cin>>n>>k;
    for(int i=1;i<=n;i++) cin>>s[i];
    for(int i=0;i<1<<k;i++) {
        cin>>c[i]>>w[i];
    }
    memset(f,-0x3f,sizeof f);
    for(int i=1;i<=n;i++) f[i][i][s[i]]=0;
    for(int l=2;l<=n;l++) {
        for(int i=1;i+l-1<=n;i++) {
            int j=i+l-1;
            int len=(l-1)%(k-1)+1;
            if(len==1) {
                for(int s=0;s<1<<k;s++) {
                    for(int x=j-1;x>=i;x-=k-1) {
                        f[i][j][c[s]]=max(f[i][j][c[s]],f[i][x][s>>1]+f[x+1][j][s&1]+w[s]);
                    }
                }
            }
            else {
                for(int s=0;s<1<<len;s++) {
                    for(int x=j-1;x>=i;x-=k-1) {
                        f[i][j][s]=max(f[i][j][s],f[i][x][s>>1]+f[x+1][j][s&1]);
                    }
                }
            }
        }
    }
    int ans=0;
    for(int i=0;i<(1<<k);i++) ans=max(ans,f[1][n][i]);
    cout<<ans;
}

原文地址:https://www.cnblogs.com/mollnn/p/12419808.html