CH5301 石子合并【区间dp】

5301 石子合并 0x50「动态规划」例题

描述

设有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堆,则代价为7,得到4 7,最后一次合并代价为11,总代价为4+7+11=22;问题是:找出一种合理的方法,使总的代价最小。输出最小代价。

输入格式

第一行一个数N表示沙子的堆数N。
第二行N个数,表示每堆沙子的质量(<=1000)。

输出格式

合并的最小代价

样例输入

4
1 3 5 2

样例输出

22

来源

CCF NOI1995

题意:

n堆石子,每堆有一个重量ai。现在想把他们合并成一堆,每次只能合并相邻的。花费的体力是合并的两堆石子重量和。要求花费体力最小。

思路:

任意时刻,任意一堆石子可以用一个闭区间[l,r]来描述,表示这堆石子是有最初的第l~r堆石子合并成的。一定存在一个整数k,在这堆石子形成前,先有l~k堆石子被合并,k+1~r堆石子被合并,然后这两堆才合并为l~r

两个长度较小的区间上的信息向一个更长的区间发生了转移,划分点k就是转移的决策。把区间长度len作为DP的阶段。

虐狗宝典笔记:

区间DP以“区间长度”作为DP的阶段,使用两个坐标(区间的左右端点)描述每个维度。区间DP中,一个状态由若干个比它更小且包含于它的区间所带代表的状态转移而来,因此区间DP的决策往往就是划分区间的方法。

实现动态规划的状态转移方程时,务必分清阶段、状态与决策,三者应该按照从外到内的顺序依次循环。

 1 //#include <bits/stdc++.h>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<stdio.h>
 6 #include<cstring>
 7 #include<map>
 8
 9 #define inf 0x3f3f3f3f
10 using namespace std;
11 typedef long long LL;
12
13 int n;
14 const int maxn = 305;
15 int a[maxn];
16 int dp[maxn][maxn], sum[maxn];
17
18 int main()
19 {
20     while(scanf("%d", &n) != EOF){
21         memset(sum, 0, sizeof(sum));
22         memset(dp, inf, sizeof(dp));
23         for(int i = 1; i <= n; i++){
24             scanf("%d", &a[i]);
25             sum[i] = sum[i - 1] + a[i];
26             dp[i][i] = 0;
27         }
28
29         for(int len = 2; len <= n; len++){
30             for(int l = 1; l <= n - len + 1; l++){
31                 int r = l + len - 1;
32                 for(int k = l; k < r; k++){
33                     dp[l][r] = min(dp[l][r], dp[l][k] + dp[k + 1][r]);
34                 }
35                 dp[l][r] += sum[r] - sum[l - 1];
36             }
37         }
38
39         printf("%d\n", dp[1][n]);
40     }
41     return 0;
42 }

原文地址:https://www.cnblogs.com/wyboooo/p/9757387.html

时间: 2024-11-09 00:57:02

CH5301 石子合并【区间dp】的相关文章

石子合并 区间dp模板

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

石子合并 区间DP模板题

题目链接:https://vjudge.net/problem/51Nod-1021 题意 N堆石子摆成一条线.现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的代价.计算将N堆石子合并成一堆的最小代价. 例如:1 2 3 4 ,有不少合并方法 1 2 3 4 => 3 3 4(3) => 6 4(9) => 10(19) 1 2 3 4 => 1 5 4(5) => 1 9(14) => 10(24) 1 2 3

石子合并(区间dp)

石子合并不应该是个区间dp? 题目:There is an old stone game.At the beginning of the game the player picks n(1<=n<=50000) piles of stones in a line. The goal is to merge the stones in one pile observing the following rules:At each step of the game,the player can me

HDU 3506 (环形石子合并)区间dp+四边形优化

Monkey Party Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)Total Submission(s): 1699    Accepted Submission(s): 769 Problem Description Far away from our world, there is a banana forest. And many lovely monkeys l

『字符合并 区间dp 状压dp』

字符合并 Description 有一个长度为 n 的 01 串,你可以每次将相邻的 k 个字符合并,得到一个新的字符并获得一定分数.得到的新字符和分数由这 k 个字符确定.你需要求出你能获得的最大分数. Input Format 第一行两个整数n,k.接下来一行长度为n的01串,表示初始串. 接下来2^k行,每行一个字符ci和一个整数wi,ci表示长度为k的01串连成二进制后按从小到大顺序得到的第i种合并方案得到的新字符,wi表示对应的第i种方案对应获得的分数. 1<=n<=300,0<

合并石子 (区间dp+前缀和)

[题目描述] N堆石子.现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分.计算出将N堆石子合并成一堆的最小得分. [题目链接] http://ybt.ssoier.cn:8088/problem_show.php?pid=1274 [算法] 若每一步决策采用贪心,则所作出的决策具有后效性,故采用动态规划.考虑决策序列,dp[i][j]表示合并i到j堆石子最少得分,状态转移方程是dp[i][j]=min(dp[i][k]+dp[k+1]

蓝桥杯:合并石子(区间DP+平行四边形优化)

http://lx.lanqiao.cn/problem.page?gpid=T414 题意:…… 思路:很普通的区间DP,但是因为n<=1000,所以O(n^3)只能拿90分.上网查了下了解了平行四边形优化:地址. 但是看不懂. 1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 const LL INF = 100000000000000000LL; 5 LL dp[1010][101

台州 OJ 2793 石子归并 区间DP

描述 有n堆石子排成一条直线,每堆石子有一定的重量.现在要合并这些石子成为一堆石子,但是每次只能合并相邻的两堆.每次合并需要消耗一定的体力,该体力为所合并的两堆石子的重量之和.问最少需要多少体力才能将n堆石子合并成一堆石子? 输入 输入只包含若干组数据.每组数据第一行包含一个正整数n(2<=n<=100),表示有n堆石子.接下来一行包含n个正整数a1,a2,a3,...,an(0<ai<=100,1<=i<=n). 输出 对应输入的数据,每行输出消耗的体力. dp[i]

2017.8.15 [Haoi2016]字符合并 区间dp+状压dp

[题目描述] 有一个长度为n的01串,你可以每次将相邻的k个字符合并,得到一个新的字符并获得一定分数.得到的新字符和分数由这k个字符确定.你需要求出你能获得的最大分数. [输入格式] 第一行两个整数n,k. 接下来一行长度为n的01串,表示初始串.输入的的相邻字符之间用一个空格隔开. 接下来2k行,每行一个字符ci和一个整数wi,ci表示长度为k的01串连成二进制后按从小到大顺序得到的第i种合并方案得到的新字符, wi表示对应的第i种方案对应获得的分数. [输出格式] 输出一个整数表示答案. [