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

\(n \leq 300, k \leq 8\)

Solution

显然长为 \(l\) 的一段可以合并成长为 \((l-1)\bmod 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;
}

相关文章:

  • 2022-03-03
  • 2021-06-01
  • 2021-07-24
猜你喜欢
  • 2021-06-06
  • 2021-10-29
  • 2021-10-24
  • 2021-07-14
  • 2022-01-09
  • 2021-10-26
  • 2021-12-15
相关资源
相似解决方案