• P1880 [NOI1995]石子合并


    题目描述

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

    试设计出1个算法,计算出将N堆石子合并成1堆的最小得分和最大得分.

    输入格式:

    数据的第1行试正整数N,1≤N≤100,表示有N堆石子.第2行有N个数,分别表示每堆石子的个数.

    输出格式:

    输出共2行,第1行为最小得分,第2行为最大得分.

    输入样例#1:

    4
    4 5 9 4
    

    输出样例#1:

    43
    54
    

    设dp[ i ] [ j ]为区间 [ i , j ]内 j - i + 1个 小堆堆成一个大堆的总分的最小/最大值。
    则 dp [ i ] [ j ] =两子区间:dp[i][k]、dp[k+1][j]得分之和加上 两个子区间石子的总和,可以用前缀和求的。

    #include<bits/stdc++.h>
    using namespace std;
    
    char buf[100000],*L=buf,*R=buf;
    #define gc() L==R&&(R=(L=buf)+fread(buf,1,100000,stdin),L==R)?EOF:*L++;
    template<typename T>
    inline void read(T&x) {
        char ch=gc(); x=0;
        while (ch<'0'||ch>'9')ch=gc();
        while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-48,ch=gc();
    }
    
    int a[220],sum[220],n,dp_min[220][220],dp_max[220][220];
    int main() {
        memset(dp_min,0x3f3f3f3f,sizeof(dp_min));
        memset(dp_max,-0x3f3f3f3f,sizeof(dp_max));
    //    freopen("in.txt","r",stdin);
        read(n);
        for(int i=1; i<=n; ++i) {
            read(a[i]);
            a[n+i]=a[i];//化环为线
        }
        for(int i=1; i<=2*n; ++i) {
            sum[i]=sum[i-1]+a[i];
            dp_min[i][i]=0;//区间内只有一个石子,不能合成
            dp_max[i][i]=0;
        }
        for(int l=2; l<=n; ++l) {// l<=>j-i+1表示长度,长度小可以推出长度大的,故最外层是l
            for(int i=1; i<=2*n+-l; ++i) {
                int j=i+l-1;
                for(int k=i; k<j; ++k) {
                    dp_min[i][j]=min(dp_min[i][j],dp_min[i][k]+dp_min[k+1][j]);//子区间总分的和的最小值
                    dp_max[i][j]=max(dp_max[i][j],dp_max[i][k]+dp_max[k+1][j]);
                }
                dp_min[i][j]+=sum[j]-sum[i-1];//再加上该次合成的得分,即为区间[i,j]的最终得分。
                dp_max[i][j]+=sum[j]-sum[i-1];
            }
        }
        int ans_min=0x3f3f3f3f,ans_max=-0x3f3f3f3f;
        for(int i=1; i<=n; ++i) {
            ans_min=min(ans_min,dp_min[i][n+i-1]);//遍历长度为n的区间,最小值即为答案。
            ans_max=max(ans_max,dp_max[i][n+i-1]);
        }
        cout<<ans_min<<endl<<ans_max;
        return 0;
    }
    
  • 相关阅读:
    Codeforces Round #452 F. Letters Removing
    bzoj 1492: [NOI2007]货币兑换Cash
    bzoj 4016: [FJOI2014]最短路径树问题
    bzoj 2109: [Noi2010]Plane 航空管制
    bzoj 1058: [ZJOI2007]报表统计
    bzoj 1016: [JSOI2008]最小生成树计数
    bzoj 1013: [JSOI2008]球形空间产生器sphere
    bzoj 1758: [Wc2010]重建计划
    bzoj 2337: [HNOI2011]XOR和路径
    一本通1668取石子
  • 原文地址:https://www.cnblogs.com/foursmonth/p/14144843.html
Copyright © 2020-2023  润新知