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;
    }

  • 相关阅读:
    Infopath Notify 弹出提示信息
    window.showModalDialog 返回值
    【转】获得正文内容中的所有img标签的图片路径
    Json Datable Convert
    Sharepoint 列表 附件 小功能
    Surgey 权限更改
    SQL 触发器用于IP记录转换
    Caml语句 查询分配给当前用户及当前组
    jquery 1.3.2 auto referenced when new web application in VSTS2010(DEV10)
    TFS diff/merge configuration
  • 原文地址:https://www.cnblogs.com/wtx2333/p/12363563.html
Copyright © 2011-2022 走看看