zoukankan      html  css  js  c++  java
  • 石子合并优化

    石子合并优化

    题目描述

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

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

    输入格式

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

    输出格式

    输出共1行,最大得分

    样例

    样例输入

    4
    4 4 5 9
    

    样例输出

    54
    

    思路分析

    • 看似是一道裸的区间dp,但关键是数据范围,如果找板子写,n3 的效率不炸才怪嘞,优化是必须的

    • 主要问题在转移方程这里(该带佬发功了):

      • 最大值有一个性质,总是在两个端点的最大者中取到。

        • 说一下我的思路:

          区间dp是在不多扩展宽度的,宽度大的,其值一定可以做到比它区间小的值要大,这样我们在扩张区间宽度时,最大值在此基础上再次处理即可

      • 转移方程:f[i][j]=max(f[i][j-1],f[i+1][j])+sum[j]-sum[i-1]

      • 另外还有四边形不等式优化,但是现对复杂,转载一下:https://blog.csdn.net/noiau/article/details/72514812

    代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    const int maxn=4010,INF=0x3f3f3f3f;
    int n,m,f[maxn][maxn],ans,a[maxn],sum[maxn];
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){    //环形就拓展长度即可
            scanf("%d",&a[i]);
            a[i+n]=a[i];
            sum[i]=a[i]+sum[i-1];
        }
        for(int i=n+1;i<=2*n;i++){
            sum[i]=sum[i-1]+a[i];
        }
        for(int d=2;d<=n;d++){ //枚举区间长度
            for(int i=1,j;(j=i+d-1)<=n*2;i++){
                f[i][j]=max(f[i][j-1],f[i+1][j])+sum[j]-sum[i-1];
            }
        }
        int ans=0;
        for(int i=1;i<=n;i++){
            ans=max(ans,f[i][i+n-1]);
        }
        printf("%d",ans);
        return 0;
    }
    
    
  • 相关阅读:
    使用IDEA 创建Mevan项目后,项目中没有Java源文件夹的解决方案
    Head FIRST HTML & CSS 16/3/15
    Head FIRST HTML & CSS 16/3/11
    hdu 5375 dp
    Thinking in java 16/3/8plus
    Thinking in java 16/3/8
    Beauty of mathematics
    Thinking in java 16/3/6
    Thinking in java 16/3/5
    SQL SERVER迁移--更换磁盘文件夹
  • 原文地址:https://www.cnblogs.com/hhhhalo/p/12861187.html
Copyright © 2011-2022 走看看