zoukankan      html  css  js  c++  java
  • 区间DP学习总结

    这段时间学习了区间DP,所以试着把学到的东西稍作总结,以备不时之需。

    学习区间DP首先要弄清区间DP是为了解决什么问题:一般的DP主要是特征是一次往往只操作一个数值或者存储可以不连续的物品的状态(比如背包问题中,每一个点存储的状态中,拿到的物品的编号并不要求一定连续)而区间DP,则是要求DP数组中每个点的状态映射到原本的数据集中都会与附近的元素有所关联,其中,连续区间的长度、起始点的位置、子区间分割点的位置都会有所变化,而这和一般的DP有所不同,故一般用区间DP。

    区间DP的一般格式(参考博客)

    for(int l=1;l<=n;l++)   //每次处理的区间的长度
        for(int i=0;i+l-1<len;i++) //每次区间的起点
            int j=i+l-1;   //每次区间的终点
            for(int k=i;k<j;k++) //区间的分割点
                //TODO:状态转移方程

    两个个例题:

    一.POJ1561

    AC代码:

    #include <stdio.h>
    #include <iostream>
    #include <string.h>
    using namespace std;
    const int maxn=105;
    
    int dp[maxn][maxn];
    int num[maxn];
    
    int main(){
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&num[i]);
        }
        
        for(int l=2;l<n;l++){
            for(int i=2;i+l<=n+1;i++){
                dp[i][i+l-1]=100000000;
                for(int k=i;k<i+l-1;k++){
                    dp[i][i+l-1]=min(dp[i][i+l-1],dp[i][k]+dp[k+1][i+l-1]+num[i-1]*num[k]*num[i+l-1]);
                }
            }
        }
        printf("%d
    ",dp[2][n]);
        return 0;    
    }

    二.POJ2955

    AC代码:

    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    using namespace std;
    const int maxn=105;
    
    char str[maxn];
    int dp[maxn][maxn];
    
    int check(char a,char b){
        if(a=='('&&b==')'){
            return 1;
        }
        if(a=='['&&b==']'){
            return 1;
        }else{
            return 0;
        }
    }
    
    int main(){
        while(scanf("%s",str)!=EOF){
            if(str[0]=='e')break;
            int len=strlen(str);
            memset(dp,0,sizeof(dp));
             
            for(int i=0;i<len;i++){
                dp[i][i]=0;
                if(check(str[i],str[i+1]))dp[i][i+1]=2;
                else dp[i][i+1]=0;
            }
            
            for(int l=3;l<=len;l++){//区间的长度 
                for(int i=0;i+l-1<len;i++){//开始的位置 
                    int j=i+l-1;
                    if(check(str[i],str[j]))dp[i][j]=dp[i+1][j-1]+2;
                    for(int k=i;k<j;k++){ //区间的分割 
                        dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j]);
                    }
                }
            }
            printf("%d
    ",dp[0][len-1]);
                    
        }
        return 0;
    }
  • 相关阅读:
    matlab软件-了解
    C# 自定义异常demo
    C#二进制对象copy
    asp.net 缓存依赖demo
    权限管理细粒度问题
    三层架构中的异常处理二
    如何解决复杂问题——结构化思维方式
    入职新公司如何熟悉项目
    专业工具使用与复杂大型项目设计管理
    十分钟学会 tmux
  • 原文地址:https://www.cnblogs.com/87hbteo/p/7196182.html
Copyright © 2011-2022 走看看