首页 > 其他 > 详细

[HAOI2016] 字符合并 - dp

时间:2020-03-05 14:51:54      阅读:60      评论:0      收藏:0      [点我收藏+]

给定一个长度为 \(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;
}

[HAOI2016] 字符合并 - dp

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

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!