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

    描述
    将 n堆石子绕圆形操场排放,现要将石子有序地合并成一堆。规定每次只能选相邻的两堆合并成新的一堆,并将新的一堆的石子数记做该次合并的得分。
    请编写一个程序,读入堆数 n及每堆的石子数,并进行如下计算:
    选择一种合并石子的方案,使得做 n−1 次合并得分总和最大。
    选择一种合并石子的方案,使得做 n−1次合并得分总和最小。
    输入
    输入第一行一个整数 n,表示有 n 堆石子。
    第二行 n 个整数,表示每堆石子的数量。
    输出
    输出共两行:
    第一行为合并得分总和最小值,
    第二行为合并得分总和最大值。
    样例输入
    4
    4 5 9 4
    样例输出
    43
    54
    提示
    对于 100% 的数据,有1≤n≤200

    区间dp基础题啊

    从长度从小往大枚举

    然后枚举左端点

    枚举中间点

    取max就可以了

    #include<bits/stdc++.h>
    using namespace std;
    inline int read(){
        char ch=getchar();
        int res=0;
        while(!isdigit(ch))ch=getchar();
        while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
        return res;
    }
    int n,f[405][405],g[405][405],a[405],sum[405];
    int main(){
        n=read();
        for(int i=1;i<=n;i++){
            a[i]=a[i+n]=read();
        }
        memset(f,127/3,sizeof(f));
        for(int i=1;i<=2*n;i++){
            sum[i]=sum[i-1]+a[i];
            f[i][i]=g[i][i]=0;
        }    
        for(int len=2;len<=2*n;len++){
            for(int l=1;l<=2*n-len+1;l++){
                if(l+len>2*n)break;
                int r=l+len-1;
                for(int k=l;k<=r;k++){
                    f[l][r]=min(f[l][k]+f[k+1][r],f[l][r]);
                    g[l][r]=max(g[l][r],g[l][k]+g[k+1][r]);
                }
                f[l][r]+=(sum[r]-sum[l-1]);
                g[l][r]+=(sum[r]-sum[l-1]);
            }
        }
        int maxn=0,minn=1e9;
        for(int i=1;i<=n;i++){
            maxn=max(maxn,g[i][i+n-1]);
            minn=min(minn,f[i][i+n-1]);
        }
        cout<<minn<<'
    '<<maxn;
    }
    
  • 相关阅读:
    Docker安装
    MVC-HtmlHelper简单总结
    D3.js
    分布式事务seata
    彻底搞懂JAVA路径问题
    idea 代码生成
    自动生成 serialVersionUID 的设置
    狂神说SSM框架系列连载
    缓存穿透、缓存击穿、缓存雪崩区别和解决方案
    多线程
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/10366431.html
Copyright © 2011-2022 走看看