洛谷 CF1107E Vasya and Binary String(區間dp)
阿新 • • 發佈:2021-10-10
傳送門
解題思路
看出是區間dp,但是就是不會設計狀態,不會寫狀態轉移方程/kk/kk
設dp[i][j][k]表示區間i到j加上左面連續k個a[i]的答案。
最後答案即為dp[1][n][0]。
狀態轉移分為兩種情況:
- 讓前k個和第i位連起來處理:dp[i+1][j][0]+w[k+1]
- 列舉斷點p,讓i+1到p-1先單獨處理完,相當於把i和p連起來:dp[i+1][p-1][0]+dp[p][j][k+1]
取個max即可。
列舉i、j、k、p,所以最後複雜度為 \(O(n^4)\)。
AC程式碼
#include<cstdio> #include<iostream> #include<cstring> #include<iomanip> #include<cmath> #include<algorithm> using namespace std; template<class T>inline void read(T &x) { x=0;register char c=getchar();register bool f=0; while(!isdigit(c))f^=c=='-',c=getchar(); while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar(); if(f)x=-x; } template<class T>inline void print(T x) { if(x<0)putchar('-'),x=-x; if(x>9)print(x/10); putchar('0'+x%10); } const int maxn=105; int n; long long a[maxn],w[maxn],dp[maxn][maxn][maxn]; string s; int main(){ ios::sync_with_stdio(false); cin>>n>>s; for(int i=1;i<=n;i++) cin>>w[i],a[i]=s[i-1]; for(int len=1;len<=n;len++){ for(int i=1;i<=n;i++){ int j=i+len-1; for(int k=0;k<=n;k++){ dp[i][j][k]=max(dp[i][j][k],dp[i+1][j][0]+w[k+1]); for(int p=i+1;p<=j;p++){ if(a[i]==a[p]) dp[i][j][k]=max(dp[i][j][k],dp[i+1][p-1][0]+dp[p][j][k+1]); } } } } cout<<dp[1][n][0]; return 0; }