zoukankan      html  css  js  c++  java
  • 洛谷 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;
    }
    
  • 相关阅读:
    用户自定义控件
    sql 动态行转列
    sql 将表B中不存在表A的数据 插入到表A中
    C#获取键盘和鼠标操作的时间的类
    滚动条加粗和panel,gridControl结合用
    第三项任务——用例建模
    第二项任务——项目需求分析
    第一项任务:团队组建及项目启动
    实验报告(结对项目)
    实验报告(个人项目)
  • 原文地址:https://www.cnblogs.com/yinyuqin/p/15389846.html
Copyright © 2011-2022 走看看