zoukankan      html  css  js  c++  java
  • 石子合并(区间dp)

    题目描述

    在一个圆形操场的四周摆放 NNN 堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。

    试设计出一个算法,计算出将 NNN 堆石子合并成 111 堆的最小得分和最大得分。

    输入格式

    数据的第 111 行是正整数 NNN,表示有 NNN 堆石子。

    222 行有 NNN 个整数,第 iii 个整数 aia_iai 表示第 iii 堆石子的个数。

    输出格式

    输出共 222 行,第 111 行为最小得分,第 222 行为最大得分。

    输入输出样例

    输入 #1
    4
    4 5 9 4
    输出 #1
    43
    54

    说明/提示

    1N100,0≤ai≤200

    dp[i][j]为从第i个位置到第j个位置的最小(大)结果;可以看成两堆合并;

    只有两堆的时候,直接将两堆合并;当大于两堆的时候,最后也是将两个堆合并;

    由此:dp【i】【j】=min(dp[i][j],dp[i][mid]+dp[mid+1][j]+sum[j]-su[i-1]);

    最大好说,最小的话,右上三角要初始化为 一个较大数,但是对角线要初始化为0;

    代码:

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    int main(){
        int n;
        cin>>n;
        int a[205];
        int sum[205]={0};
        int dp1[205][205],dp2[205][205];
    //    memset(dp1,0,sizeof(dp1));
    //    memset(dp2,-1,sizeof(dp2));
        for(int i=1;i<=n;i++){
            cin>>a[i];
            a[n+i]=a[i];
        }
        for(int i=1;i<=2*n;i++){
            sum[i]=sum[i-1]+a[i];
            dp1[i][i]=0;
        }
        for(int i=1;i<=2*n;i++){
            for(int j=i;j<2*n;j++){
                if(j==i)dp1[i][j]=0;
                else dp1[i][j]=1000000;
            }
        }
    /*        for(int i=1;i<=2*n;i++){
            for(int j=1;j<=2*n;j++){
                cout<<dp1[i][j]<<" ";
            }
            cout<<endl;
        }
        cout<<"************"<<endl;    */
        for(int i=2;i<=n;i++){
            for(int l=1,r;l<2*n-i+1;l++){
            //    dp1[l][r]=100000;
            //    dp2[l][r]=-1;
                r=l+i-1;
                for(int mid=l;mid<r;mid++){
                    dp1[l][r]=min(dp1[l][r],dp1[l][mid]+dp1[mid+1][r]+sum[r]-sum[l-1]);
                    dp2[l][r]=max(dp2[l][r],dp2[l][mid]+dp2[mid+1][r]+sum[r]-sum[l-1]);
                }
            }
        }
    /*        for(int i=1;i<=2*n;i++){
            for(int j=1;j<=2*n;j++){
                cout<<dp1[i][j]<<" ";
            }
            cout<<endl;
        }*/
        int ans1=123456789,ans2=-1;
        for(int i=1;i<=n;i++){
            ans1=min(ans1,dp1[i][i+n-1]);
            ans2=max(ans2,dp2[i][i+n-1]);
        }
        cout<<ans1<<endl<<ans2<<endl;
    }

  • 相关阅读:
    ZOJ 3735 Cake(区间DP,最优三角剖分)
    POJ 1185 炮兵阵地 (状态压缩DP)
    POJ 3415 Common Substrings (后缀数组,长度不小于k的公共子串的个数)
    NSNumberFormatter 千分符
    遭遇String.getBytes()
    HDFS数据的Checksum
    hadoop mapreduce作业流程概论
    HDFS 安全模式
    hadoop的dfs.replication
    hadoop升级
  • 原文地址:https://www.cnblogs.com/wtx2333/p/12363563.html
Copyright © 2011-2022 走看看