9-合并石子

/*                                             石子合并(一)
                  时间限制:1000 ms  |  内存限制:65535 KB
                      难度:3

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

求出总的代价最小值。

输入
    有多组测试数据,输入到文件结束。
    每组测试数据第一行有一个整数n,表示有n堆石子。
    接下来的一行有n(0< n <200)个数,分别表示这n堆石子的数目,用空格隔开
输出
    输出总代价的最小值,占单独的一行
样例输入

3
    1 2 3
    7
    13 7 8 16 21 4 18

样例输出

9
    239

*/
//区间dp: 状态转移方程为 dp[i][j] = min(dp[i][k] + dp[k+1][j])(i <= k <j) + sum[j] - sum[i - 1].
//通过枚举每一个区间的可能长度2~n,循环求解min();

#include <iostream>
#include <cstring>
#include <cstdio>
#define MAX 2 << 16
using namespace std;
int dp[205][205], sum[205];
int a[205];

int main(){
    int n;
    while(~scanf("%d", &n)){
//        memset(a, 0, sizeof(a));
        memset(dp, 0, sizeof(dp));
        memset(sum, 0, sizeof(sum));
        for(int i = 1; i <= n; i++){
            scanf("%d", &a[i]);
            sum[i] = sum[i - 1] + a[i]; //为保正i-1不越界故i从1开始取
        }
        for(int r = 2; r <= n; r++){ //枚举所有可能的区间长度
            for(int i = 1; i + r - 1 <= n; i++){
                int j = i + r - 1;   //i确定了,区间长度确定了,j也就确定了
                dp[i][j] = MAX;
                for(int k = i; k <= j - 1; k++)
                    if(dp[i][j] > dp[i][k] + dp[k+1][j] + sum[j] - sum[i - 1])
                        dp[i][j] = dp[i][k] + dp[k+1][j] + sum[j] - sum[i -1];                
            }
        }
        printf("%d\n", dp[1][n]);
    }
    return 0;
}

时间: 2024-10-05 23:09:27

9-合并石子的相关文章

合并石子 区间dp水题

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

合并石子大总结

合并石子大总结 石子合并问题是最经典的DP问题.首先它有如下3种题型: 一.非相邻两堆石子合并 有N堆石子,现要将石子有序的合并成一堆,规定如下:每次只能移动任意的2堆石子合并,合并花费为新合成的一堆石子的数量.求将这N堆石子合并成一堆的总花费最小(或最大). 分析:当然这种情况是最简单的情况,合并的是任意两堆,直接贪心即可,每次选择最小的两堆合并.本问题实际上就是哈夫曼的变形. 二.直线型相邻两堆石子合并 有N堆石子,现要将石子有序的合并成一堆,规定如下:每次只能移动相邻的2堆石子合并,合并花

环形合并石子

[题目描述] 在一个圆形操场的四周摆放N堆石子(N≤100),现要将石子有次序地合并成一堆.规定每次只能选相邻的两堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分.编一程序,读入堆数N及每堆石子数(≤100)选择一种合并石子的方案,分别得到合并这N堆石子为一堆,可以得到的最大得分和最小得分 [输入描述] 输入包含多个例子.第一行为N,即石子堆的数目,以下一行为N个整形,分别代表每堆石子的数目.当N=0时,输入结束. [输出描述] 对每个例子,输出其最小得分和最大得分,这两个数值以空格间

合并类动态规划,石子归并,合并石子解题报告

石子归并问题 1:任意版 有N堆石子,现要将石子有序的合并成一堆,规定如下:每次只能移动任意的2堆石子合并,合并花费为将的一堆石子的数量.设计一个算法,将这N堆石子合并成一堆的总花费最小(或最大). 此类问题比较简单,就是哈夫曼编码的变形,用贪心算法即可求得最优解.即每次选两堆最少的,合并成新的一堆,直到只剩一堆为止.证明过程可以参考哈夫曼的证明过程. 2.链式归并 问题描述 设有N堆沙子排成一排,其编号为1,2,3,-,N(N<=100).每堆沙子有一定的数量.现要将N堆沙子并成为一堆.归并的

NYOJ 737 合并石子(一)

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

合并石子 四边形不等式优化

题目描述 有一排石子,共n 堆.现要将石子有次序地合并成一堆.规定每次只能选相邻的2 堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分.试设计一个算法,计算出将n堆石子合并成一堆的最小得分. 题解 首先由直接动态规划的方法来做,即 for(int i=1;i<=n;i++) for(int j=i;j<=n;j++) for(int k=i;k<=j;k++) { f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+cost[j]-cost[i-1]);

蒟蒻吃药计划-治疗系列 #round 2 合并石子+乘积最大

1.合并石子 <信息学奥赛一本通>第五版 P371 第三节 T1 我就直接开始讲吧: Warning:这个题目和 合并果子 不一样!不一样!不一样!不一样!不一样!不一样!不一样!不一样! :我想告诉你一个事情,你帮帮我好么? (内心:mmp怎么又是这个人) :昨天我去商场的时候,钱包被偷了,银行卡啥的都没了,你能帮帮我么? (内心:凭啥,我就不帮) :如果你帮我找到的话,我给你50金币好不好? (*听到这句话,你充满了决心) 好吧,那我们帮帮他吧,让我们先看看他遇到了什么问题 :那个小偷在我

【四边形不等式】COGS1658- [HZOI 2014] 合并石子

[题目大意] 在一个园形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分.试设计出1个算法,计算出将N堆石子合并成1堆的最小得分和最大得. [思路] 设 dp[i][j] 表示第 i 到第 j 堆石子合并的最优值,sum[i][j] 表示第 i 到第 j 堆石子的总数量. 1 #include<iostream> 2 #include<cstdio> 3 using namespace std;

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 分析

算法提高 合并石子(DP)

问题描述 在一条直线上有n堆石子,每堆有一定的数量,每次可以将两堆相邻的石子合并,合并后放在两堆的中间位置,合并的费用为两堆石子的总数.求把所有石子合并成一堆的最小花费. 输入格式 输入第一行包含一个整数n,表示石子的堆数. 接下来一行,包含n个整数,按顺序给出每堆石子的大小 . 输出格式 输出一个整数,表示合并的最小花费. 样例输入 51 2 3 4 5 样例输出 33 数据规模和约定 1<=n<=1000, 每堆石子至少1颗,最多10000颗. 题解 #include<stdio.h