区间DP——石子合并问题

述    有N堆石子排成一排,每堆石子有一定的数量。现要将N堆石子并成为一堆。合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆。求出总的代价最小值。

输入
有多组测试数据,输入到文件结束。
每组测试数据第一行有一个整数n,表示有n堆石子。
接下来的一行有n(0< n <200)个数,分别表示这n堆石子的数目,用空格隔开
输出
输出总代价的最小值,占单独的一行
样例输入
3
1 2 3
13 7 8 16 21 4 18
大意:如题意:用一个k记录从是第几次,然后i从1开始到n-k-1结束,j=i+l-1表示,插入m,所以要sum[j]-sum[i-1]
O(n^3)代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAX = 1000;
const int inf = 9999999;
int dp[MAX][MAX],ans[MAX],sum[MAX];
int main()
{
    int n;
    scanf("%d",&n);
    memset(dp,0,sizeof(dp));
    sum[0] = 0;
    for(int i = 1; i <= n ; i++){
        scanf("%d",&ans[i]);
        sum[i] = sum[i-1] + ans[i];
    }
    int k,i,j;
    for(int k = 2; k <= n ; k++){
        for(int i = 1; i <= n - k + 1;i++){
            j = i + k - 1;
           dp[i][j] = inf;
           for(int m = i; m < j ; m++){
                dp[i][j] = min(dp[i][j],dp[i][m]+dp[m+1][j]+sum[j]-sum[i-1]);
           }
        }
    }
   printf("%d\n",dp[1][n]);
  return 0;
}

可以用平行四边形优化,即用一个数组s来存储每个最优位置。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int MAX = 1000;
    const int inf = 9999999;
    int dp[MAX][MAX],ans[MAX],sum[MAX],s[MAX][MAX];
    int main()
    {
        int n;
        scanf("%d",&n);
        memset(dp,0,sizeof(dp));
        sum[0] = 0;
        for(int i = 1; i <= n ; i++){
            scanf("%d",&ans[i]);
            sum[i] = sum[i-1] + ans[i];
            s[i][i] = i;
        }
        int k,i,j;
        for(int k = 2; k <= n ; k++){
            for(int i = 1; i <= n - k + 1;i++){
                j = i + k - 1;
               dp[i][j] = inf;
               for(int m = s[i][j-1]; m <= s[i+1][j];m++){
                   if(dp[i][j] > dp[i][m]+dp[m+1][j]+sum[j]-sum[i-1]){
                       dp[i][j] = dp[i][m]+dp[m+1][j]+sum[j]-sum[i-1];
                       s[i][j] = m;
                 }
               }
            }
        }
       printf("%d\n",dp[1][n]);
      return 0;
    }

时间: 2024-12-23 06:09:54

区间DP——石子合并问题的相关文章

四边形不等式优化DP——石子合并问题 学习笔记

好方啊马上就要区域赛了连DP都不会QAQ 毛子青<动态规划算法的优化技巧>论文里面提到了一类问题:石子合并. n堆石子.现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分. 求出将n堆石子合并成一堆的最小得分和最大得分以及相应的合并方案. 设m[i,j]表示合并d[i..j]所得到的最小得分. 状态转移方程: 总的时间复杂度为O(n3). [优化方案] 四边形不等式: m[i,j]满足四边形不等式 令s[i,j]=max{k | m[

合并石子 区间dp水题

合并石子 链接: nyoj 737 描述: 有N堆石子排成一排,每堆石子有一定的数量.现要将N堆石子并成为一堆.合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆.求出总的代价最小值. tags:最基本的区间dp,这题范围小,如果n大一些,还是要加个平行四边行优化. #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring&g

[NYIST737]石子合并(一)(区间dp)

题目链接:http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=737 很经典的区间dp,发现没有写过题解.最近被hihocoder上几道比赛题难住了,特此再回头重新理解一遍区间dp. 这道题的题意很明确,有一列石子堆,每堆石子都有数量,还有一个操作:相邻两堆石子合并成一堆石子,这个操作的代价是这两堆石子的数目和.要找一个合并次序,使得代价最小,最终输出最小代价. 这个题可以用动态规划,简单分析可以得知,这一列石子堆都可以划分为小区间,每个小区间

区间DP [NYOJ 737] 石子合并(一)

石子合并(一) 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述     有N堆石子排成一排,每堆石子有一定的数量.现要将N堆石子并成为一堆.合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆.求出总的代价最小值. 输入 有多组测试数据,输入到文件结束.每组测试数据第一行有一个整数n,表示有n堆石子.接下来的一行有n(0< n <200)个数,分别表示这n堆石子的数目,用空格隔开 输出 输出总代价的最小值,占单

石子合并问题(一) (基础的区间dp)

石子合并(一) 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述     有N堆石子排成一排,每堆石子有一定的数量.现要将N堆石子并成为一堆.合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆.求出总的代价最小值. 输入 有多组测试数据,输入到文件结束. 每组测试数据第一行有一个整数n,表示有n堆石子. 接下来的一行有n(0< n <200)个数,分别表示这n堆石子的数目,用空格隔开 输出 输出总代价的最小值,

石子合并(区间dp)

石子合并(一) 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述     有N堆石子排成一排,每堆石子有一定的数量.现要将N堆石子并成为一堆.合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆.求出总的代价最小值. 输入 有多组测试数据,输入到文件结束. 每组测试数据第一行有一个整数n,表示有n堆石子. 接下来的一行有n(0< n <200)个数,分别表示这n堆石子的数目,用空格隔开 输出 输出总代价的最小值,

zjnu 1181 石子合并(区间DP)

Description 在操场上沿一直线排列着 n堆石子.现要将石子有次序地合并成一堆.规定每次只能选相邻的两堆石子合并成新的一堆, 并将新的一堆石子数记为该次合并的得分.允许在第一次合并前对调一次相邻两堆石子的次序. 计算在上述条件下将n堆石子合并成一堆的最小得分. Input 输入数据共有二行,其中,第1行是石子堆数n≤100: 第2行是顺序排列的各堆石子数(≤20),每两个数之间用空格分隔. Output 输出合并的最小得分. Sample Input 3 2 5 1 Sample Out

区间DP理解 (石子合并)

设有N堆沙子排成一排,其编号为1,2,3,-,N(N<=300).每堆沙子有一定的数量,可以用一个整数来描述,现在要将这N堆沙子合并成为一堆,每次只能合并相邻的两堆,合并的代价为这两堆沙子的数量之和,合并后与这两堆沙子相邻的沙子将和新堆相邻,合并时由于选择的顺序不同,合并的总代价也不相同,如有4堆沙子分别为 1  3  5  2 我们可以先合并1.2堆,代价为4,得到4 5 2 又合并 1,2堆,代价为9,得到9 2 ,再合并得到11,总代价为4+9+11=24,如果第二步是先合并2,3堆,则代

NOI 1995 合并石子 区间DP

题目 题目描述 在一个圆形操场的四周摆放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 分析