zoukankan      html  css  js  c++  java
  • Codevs 3002 石子归并 3(DP四边形不等式优化)

    3002 石子归并 3
    时间限制: 1 s
    空间限制: 256000 KB
    题目等级 : 钻石 Diamond
    题目描述 Description
    有n堆石子排成一列,每堆石子有一个重量w[i], 每次合并可以合并相邻的两堆石子,一次合并的代价为两堆石子的重量和w[i]+w[i+1]。问安排怎样的合并顺序,能够使得总合并代价达到最小。
    输入描述 Input Description
    第一行一个整数n(n<=3000)
    第二行n个整数w1,w2…wn (wi <= 3000)
    输出描述 Output Description
    一个整数表示最小合并代价
    样例输入 Sample Input
    4
    4 1 1 4
    样例输出 Sample Output
    18
    数据范围及提示 Data Size & Hint
    数据范围相比“石子归并” 扩大了
    分类标签 Tags
    动态规划 区间型DP 单调性DP

    Here 证明啥的都讲得比较清楚

    /*
    DP四边形不等式优化. 
    可证得k取[s[i][j-1],s[i+1][j]]
    然后n^2搞就好.
    */
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define MAXN 3001
    using namespace std;
    int n,m,f[MAXN][MAXN],s[MAXN][MAXN],w[MAXN];
    int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
        return x*f;
    }
    void slove()
    {
        for(int i=1;i<=n;i++) s[i][i]=i;
        f[0][0]=0;
        for(int l=1;l<=n-1;l++)
          for(int i=1;i<=n-l;i++)
          {
            int j=i+l;
            for(int k=s[i][j-1];k<=s[i+1][j];k++)
            {
                if(f[i][j]>f[i][k]+f[k+1][j]+w[j]-w[i-1])
                {
                    f[i][j]=f[i][k]+f[k+1][j]+w[j]-w[i-1];
                    s[i][j]=k;
                }
              }
          }
    }
    int main()
    {
        int x;
        memset(f,127/3,sizeof f);
        n=read();
        for(int i=1;i<=n;i++) x=read(),w[i]=w[i-1]+x,f[i][i]=0;
        slove();
        printf("%d",f[1][n]);
        return 0;
    }
  • 相关阅读:
    BZOJ 3677 连珠线
    BZOJ 3676 回文串
    BZOJ 3675 序列分割
    BZOJ 4013 实验比较
    BZOJ 4011 落忆枫音
    使用Google BBR加速 VPS
    OSX编译安装Python3及虚拟开发环境Virtualenv
    OSX安装Mysql8.0
    OpenSSL编程之摘要
    OpenCA搭建
  • 原文地址:https://www.cnblogs.com/nancheng58/p/10068027.html
Copyright © 2011-2022 走看看