zoukankan      html  css  js  c++  java
  • P1880石子合并

    1995年的noi区间dp题,这道题AC耗时达到了数月。

    有一道题叫做果子合并,也是求合并的最小花费,但是那个题是可以随便合并两堆,但是这个题只能合并相邻的两堆,并且是一个环。对于环的问题,我们一般可以特判i==1和i==n或者倍增转化成链的问题,长度为两倍的时候即可涵盖所有环的情况。meanwhile我们发现了一个问题,当前要合并的两堆一定是要重合的,所以转化到了区间的问题,然后每一个最优子结构的状态是由其中的两个小小最优子结构而转移来的,所以枚举分割点即可。这样就建立了区间dp的模型。要注意最后还要进行判断,因为起点是1~2n。

    1.熟记这个区间dp模型,当成模板题

    2.分析每一个状态是怎么来的

    3.正确处理环的做法

    代码

    #include<bits/stdc++.h>
    #define maxn 300
    using namespace std;
    int dpMin[maxn][maxn];
    int dpMax[maxn][maxn];
    int a[maxn];//石头数目 
    int sum[maxn];//前缀和
    int n; 
    int main(){
        cin>>n;
        for(int i=1;i<=n;i++){
            cin>>a[i];
            a[i+n]=a[i];
        }
        for(int i=1;i<=n*2;i++){
            sum[i]=sum[i-1]+a[i];//前缀和
        }
        memset(dpMax,-1,sizeof dpMax);
        memset(dpMin,0x3f,sizeof dpMin);
        for(int i=1;i<=n*2;i++){
            dpMin[i][i]=0;
            dpMax[i][i]=0;
        }
        //区间DP 
        for(int len=2;len<=n;len++){
            for(int i=1;i<=n*2;i++){
                int j=i+len-1;
                if(j>2*n) break;
                for(int k=i;k<j;k++){
                    dpMin[i][j]=min(dpMin[i][j],dpMin[i][k]+dpMin[k+1][j]+sum[j]-sum[i-1]);
                    dpMax[i][j]=max(dpMax[i][j],dpMax[i][k]+dpMax[k+1][j]+sum[j]-sum[i-1]);
                }    
            }
        }
        int ansMax=dpMax[1][n];
        int ansMin=dpMin[1][n];
        for(int i=1;i<=n;i++){
            ansMax=max(dpMax[i][i+n-1],ansMax);
            ansMin=min(dpMin[i][i+n-1],ansMin);
        } 
        cout<<ansMin;    
        puts(" ");    
        cout<<ansMax;
        return 0;
    }
  • 相关阅读:
    Spring Boot开发Web应用
    使用阿里云Docker镜像加速
    六种微服务架构的设计模式
    HashMap按键排序和按值排序
    Docker搭建本地私有仓库
    Ubuntu 14.04主机上部署k8s集群
    Ubuntu 16.04下搭建kubernetes集群环境
    Docker中images中none的镜像删除
    docker 下 alpine 镜像设置时区的有效办法
    offsetLeft和style.left的区别
  • 原文地址:https://www.cnblogs.com/china-mjr/p/11663221.html
Copyright © 2011-2022 走看看