石子合并——最经典的dp问题

石子合并三大题型

  1. 任意两堆石子合并,直接手写一个小根堆,每次取前面两个相加,得到的值继续放入优先队列中,直到里面只有一个元素就输出
  2. 只能合并相邻两堆石子,这就类似于矩阵连乘(传送门),不过还是有一些差别
  3. 在2的基础上,这些石子形成一个环形,这又是一种新的题型
今天记录的是第二种——区间dp

题目描述
在一条直线上有n堆石子,每堆有一定的数量,每次可以将两堆相邻的石子合并,合并后放在两堆的中间位置,合并的费用为两堆石子的总数。求把所有石子合并成一堆的最小花费。例如:输入{1,2,3,4,5},输出33。【3+6+9+15=33】
输入
本题应该处理到文件尾,每组输入包括两行,第一行为石子堆的个数n,第二行则为每堆石子的个数。
输出
输出最小花费。
样例输入
5
1 2 3 4 5
样例输出
33

ps:

首先分析一下这个题目,举个例子,如果只有三堆 4 , 5 , 9
我们合并这三堆所花费的来自三部分

  • 第一二堆合并的花费
  • 第一二堆石子的个数和
  • 第三堆石子的数量
  • 那么就是4+5+9+6=24

但是这个题目要求的是相邻两堆之间合并,如果又很多堆石子,那么我们就要去找断点,最优值问题就是一个个最优子结构,所以我们需要一个一个去找断点,算出每一个最优子结构,然后相加

转移方程如下

在这里插入图片描述
此外我们需要引入一个数组,来记录石子的数量,可以利用前缀和思想,也可以直接存储第i到第j石子的数量

在这里插入图片描述
前缀优化

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 1e3 + 5;
int a[maxn], b[maxn], dp[maxn][maxn];
int main()
{
   
   int n;
   while (~scanf("%d", &n))
   {
   
      memset(dp, <
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值