cf1600-1900每天刷2-3道打卡(2)
上一个帖子太长了,编辑起来有点卡干脆重开了一个
Day20------2025.6.03
Problem - E - Codeforces
E. Vasya and Binary String(区间dp)
思路
这其实是一道2400的题,因为最近温习了一下区间dp学习到了这个带有前缀思维的区间dp的状态转移于是就做了这么一个题,话说这个前缀的思维确实很难想到,总之量变引起质变下次遇到的时候就会了
我们设表示区间 l...r 的范围内有k个前缀和s[l]相同的字符与s[l]相连,
那么我们在状态转移的时候分为两种情况:
1.将s[l]连同这k个前缀全部消掉
2.将连同s[l]的k+1个前缀向后转移,不断枚举断点即可
代码
#include<bits/stdc++.h>
using namespace std;#define vcoistnt ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
#define int long long
#define vi vector<int>
#define vb vector<bool>
typedef pair<int,int> pll;const int N=2e5+10;
const int inf=1e18;
const int mod=998244353;//s[l...r]其中有k个和s[l]相等的字符与s[l]相连的最优解
int dfs(int l,int r,int k,string s,vi a,vector<vector<vector<int>>>& dp){if(l==r){return a[k+1];}if(l>r){return 0;}if(dp[l][r][k]!=-1) return dp[l][r][k];int ans=0;//将前缀全部清除ans=max(ans,a[k+1]+dfs(l+1,r,0,s,a,dp));//将前缀向后转移for(int i=l+1;i<=r;i++){if(s[i]==s[l]){ans=max(ans,dfs(l+1,i-1,0,s,a,dp)+dfs(i,r,k+1,s,a,dp));}}return dp[l][r][k]=ans;
}void solve(){int n;string s;cin>>n>>s;s=" "+s;vector<int> a(n+10);for(int i=1;i<=n;i++) cin>>a[i];vector<vector<vector<int>>> dp(n+1,vector<vector<int>>(n+1,vector<int>(n+1,-1)));cout<<dfs(1,n,0,s,a,dp)<<"\n";
}
signed main() {vcoistntcout<<fixed<<setprecision(2);int _=1;// cin>>_;while(_--) solve();return 0;
}