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

    一.试题
    在一个园形操场的四周摆放N堆石子(N≤100),现要将石子有次序地合并成一堆。规定
    每次仅仅能选相邻的两堆合并成新的一堆,并将新的一堆的石子数。记为该次合并的得分。
    编一程序。由文件读入堆数N及每堆的石子数(≤20)。
    ①选择一种合并石子的方案,使得做N-1次合并,得分的总和最小。
    ②选择一种合并石子的方案,使得做N-1次合并。得分的总和最大。


    比如,所看到的的4堆石子,每堆石子数(从最上面的一堆数起。顺时针数)依
    次为4594。则3次合并得分总和最小的方案:8+13+22=43
    得分最大的方案为:14+18+22=54



    </pre><pre name="code" class="cpp">#include<iostream>
    #include<stdio.h>
    #include<math.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    #define N 105
    //定义二维数组m[i][j]来记录i到j的合并过成中最少石子数目
    int solve_min(int *p,int n)
    {
        int i,j,k,r,sum;
        int m[N][N];
        memset(m,-1,sizeof(m));
        for(i=1; i<=n; i++)   //当一个单独合并时,m[i][i]设为0,表示没有石子
            m[i][i]=0;
        for(i=1; i<n; i++)  //当相邻的两堆石子合并时。此时的m非常easy能够看出是两者之和
            m[i][i+1]=p[i]+p[i+1];
        for(r=3; r<=n; r++) //当相邻的3堆以及到最后的n堆时,运行下面循环
        {
            for(i=1; i<=n-r+1; i++)
            {
                j=i+r-1;
                sum=0;
                for(k=i; k<=j; k++)   //当i到j堆石子合并时最后里面的石子数求和得sum
                    sum+=p[k];
                m[i][j]=m[i+1][j]+sum;
    // 此时m[i][j]为i~j堆石子间以m[i][i]+m[i+1][j]+sum结果。这是当中一种可能,不一定是最优
                for(k=i+1; k<j; k++)
                {
                    int t=m[i][k]+m[k+1][j]+sum;
                    if(t<m[i][j])
                        m[i][j]=t;
                }
            }
        }
        return m[1][n];
    }
    int solve_max(int *p,int n)
    {
        int i,j,k,r,sum;
        int m[N][N];
        memset(m,-1,sizeof(m));
        for(i=1; i<=n; i++)
            m[i][i]=0;
        for(i=1; i<n; i++)
            m[i][i+1]=p[i]+p[i+1];
        for(r=3; r<=n; r++)
        {
            for(i=1; i<=n-r+1; i++)
            {
                j=i+r-1;
                sum=0;
                for(k=i; k<=j; k++)
                    sum+=p[k];
                m[i][j]=m[i+1][j]+sum;
                for(k=i+1; k<j; k++)
                {
                    int t=m[i][k]+m[k+1][j]+sum;
                    if(t>m[i][j])
                        m[i][j]=t;
                }
            }
        }
        return m[1][n];
    }
    int main()
    {
        int i,j,k,n,stone[N];
        while(scanf("%d",&n)!=-1)
        {
            for(i=1; i<=n; i++)
            {
                scanf("%d",&stone[i]);
            }
            int mmin=solve_min(stone,n);
            int mmax=solve_max(stone,n);
            for(j=1; j<n; j++)
            {
                int t=stone[1];
                for(k=1; k<n; k++)
                {
                    stone[k]=stone[k+1];
                }
                stone[n]=t;
                int tmin=solve_min(stone,n);
                int tmax=solve_max(stone,n);
                if(tmin<mmin)
                    mmin=tmin;
                if(tmax>mmax)
                    mmax=tmax;
            }
            printf("%d
    %d
    ",mmin,mmax);
        }
        return 0;
    }
    
    


  • 相关阅读:
    “Swift Language Version” (SWIFT_VERSION) build setting must be set to a supported value for targets which use Swift
    webSocket通讯
    动画效果
    史上最简单MySQL教程详解(进阶篇)之视图
    “野生”程序猿写博客一年的感悟
    成都“小甜甜”:她给了男人希望,男人却被嘲笑X丝
    史上最简单MySQL教程详解(进阶篇)之索引及失效场合总结
    SpringBoot简明教程之快速创建第一个SpringBoot应用
    史上最简单MySQL教程详解(进阶篇)之深入理解事务处理内部的动作
    史上最简单MySQL教程详解(进阶篇)之锁与事务处理分离水平(二)
  • 原文地址:https://www.cnblogs.com/zhchoutai/p/8440998.html
Copyright © 2011-2022 走看看