洛谷 CF1107E Vasya and Binary String(区间dp)
传送门
解题思路
看出是区间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;
}

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号