码迷,mamicode.com
首页 > 其他好文 > 详细

Educational Codeforces Round 59 (Rated for Div. 2) E 区间dp + 状态定义

时间:2019-05-04 16:16:09      阅读:156      评论:0      收藏:0      [点我收藏+]

标签:fine   tor   题意   lock   name   uri   ++   +=   https   

https://codeforces.com/contest/1107/problem/E

题意

给出01字符串s(n<=100),相邻且相同的字符可以同时消去,一次性消去i个字符的分数是\(a[i]\),问消去s最多能得到多少分数

题解

  • 实质是安排消去次序使得分数最大,第一步采取的行动是递归边界
  • 因为只有01串,所以s被分成了一段一段,考虑段处理
  • 预处理出一次性消去i个字符的最大分数\(f[i]\)
  • 定义\(dp[l][r][cnt]\)为消去第l到第r段加上cnt个字符和第l段相同得到的最大分数
  • 每个区间只考虑第l段消去的情况(立刻消去or和后面的一起消去)
ans=dfs(l+1,r,0)+f[cnt+b[l]];  //立刻消去第l段
for(int i=l+2;i<=r;i+=2){
    ans=max(ans,dfs(l+1,i-1,0)+dfs(i,r,b[l]+cnt)); //枚举第二段的分割点,dfs(第二段)+dfs(第l段+第三段)
}

代码

#include<bits/stdc++.h>
#define ll long long 
#define MAXN 105
using namespace std;
ll f[MAXN],dp[MAXN][MAXN][MAXN],a[MAXN];
vector<int>b;
string s;
int n,cnt=0;
ll dfs(int l,int r,int cnt){
    if(l>r)return f[cnt];
    ll &ans=dp[l][r][cnt];
    if(ans!=-1)return ans;
    ans=dfs(l+1,r,0)+f[cnt+b[l]];
    for(int i=l+2;i<=r;i+=2)
        ans=max(ans,dfs(l+1,i-1,0)+dfs(i,r,b[l]+cnt));
    return ans;
}
int main(){
    cin>>n>>s;
    for(int i=1;i<=n;i++)cin>>a[i];
    f[1]=a[1];
    for(int i=2;i<=n;i++){
        f[i]=a[i];
        for(int j=1;j<i;j++)
            f[i]=max(f[i],f[j]+f[i-j]);
    }
    memset(dp,-1,sizeof(dp));
    for(int i=0;i<n;i++){
        if(i==0||s[i]==s[i-1])cnt++;
        else{
            b.push_back(cnt);
            cnt=1;
        }
    }
    b.push_back(cnt);
    cout<<dfs(0,b.size()-1,0);
}

Educational Codeforces Round 59 (Rated for Div. 2) E 区间dp + 状态定义

标签:fine   tor   题意   lock   name   uri   ++   +=   https   

原文地址:https://www.cnblogs.com/VIrtu0s0/p/10808744.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!