石子合并问题DP
START:
2021-08-10
14:29:04
1.问题描述:
有N堆石子排成一排,每堆石子有一定的数量。现要将N堆石子并成为一堆。合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆。求出总的代价最小值。
2. 输入输出示例
输入
有多组测试数据,输入到文件结束。
每组测试数据第一行有一个整数n,表示有n堆石子。
接下来的一行有n(0< n <200)个数,分别表示这n堆石子的数目,用空格隔开
输出
输出总代价的最小值,占单独的一行
样例输入
2
3
1 2 3
7
13 7 8 16 21 4 18
样例输出
9
239
3.分析:
由题目我们可知,题目将给我们测试数据的组数,我们定义一个变量t来储存,用while(t--)来处理了这t组数据。
对于每组数据,我们首先会得到有n堆的石子,然后得到这n堆石子每堆石子的数目。
处理完数据,我们得设计算法来解题了:
对于不同的顺序,我们合并石子的代价不同。
我们举个栗子,给定4个石堆,分别有1个,2个,3个,4个石堆,我们先全部遍历一遍,比如,先只遍历长度为2的合并,看看有什么规律:
我们可以看到,有四个石堆,分别有1个,2个,3个, 4个石头,我们先执行长度为2的合并:我们用sum[i][j]表示从i合并到j需要多少代价,dp[i][j]表示合并区间[ i , j ]的石堆累计的代价
第一种:1∪2==>sum[1][2]=1+2=3,dp[1][2]=3
第二种:2∪3==>sum[2][3]=2+3=5,dp[2][3]=5
第三种:3∪4==>sum[3][4]=3+4=7,dp[3][4]=7
我们只有四个石堆,所以合并长度为2的方案只有这三个,然后接着我们合并长度为3的:
合并区间[ 1 , 3 ]有以下两种方案:
第一种:合并{1∪2,3},所以(1∪2)∪3:
sum[1][3]=sum[1][2]+sum[3][3]=3+3=6
dp[1][3]=sum[1][2]+sum[1][3]=3+6=9
第二种:合并{1,2∪3},所以1∪(2∪3):
sum[1][3]=sum[1][1]+sum[2][3]=1+5=6
dp[1][3]=sum[2][3]+sum[1][3]=5+6=11
所以合并区间[1,3]的最优方案是先合并1,2再合并3。
由此我们知道,合并区间[i,j]的最小代价是由:
已经有的合并代价最小值dp[i][j],和从i 到k的最小代价、从k+1到j的最小代价、从i到j的合并代价的和取最小值
程序结构:
关于核心函数solve(),我们该怎么写,我们程序结构里一共有三层for循环:
最外层循环是循环枚举合并长度,从1~n-1
第二层循环是循环枚举每次合并长度固定的时候的起点
第三层循环是循环枚举合并区间固定时,分界线的位置。
其实这个做法的核心不是看合并区间的长度和起点的位置,而是最后一层的分界线的位置:
因为对于每种合并,都有分界线,那么最后一次合并的时候,一定有一个最终分界线,我们最小代价就是在这道分界线上取得的。
对于状态转移公式:dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[i][j]),我们一定要确保我们在计算dp[i][j]的时候,
dp[i][k],dp[k+1][j],sum[i][j]都是已经计算好了的。
for (int i = 1; i <= n; i ++) {
cin >> a[i];
s[i] += s[i - 1] + a[i];
} // 区间 DP 枚举套路:长度+左端点
for (int len = 1; len < n; len ++) { // len表示i和j堆下标的差值
for (int i = 1; i + len <= n; i ++) {
int j = i + len; // 自动得到右端点
dp[i][j] = 1e8;
for (int k = i; k <= j - 1; k ++) { // 必须满足k + 1 <= j
dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j] + s[j] - s[i - 1]);
}
}
}
最后输出dp[1][n]就行了
END:
2021-08-10
15:43:10
石子合并问题DP的更多相关文章
- 洛谷P1880 石子合并(环形石子合并 区间DP)
题目描述 在一个圆形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分. 试设计出1个算法,计算出将N堆石子合并成1 ...
- 洛谷 P1880 [NOI1995] 石子合并(区间DP)
传送门 https://www.cnblogs.com/violet-acmer/p/9852294.html 题解: 这道题是石子合并问题稍微升级版 这道题和经典石子合并问题的不同在于,经典的石子合 ...
- 石子合并 区间dp模板
题意:中文题 Description 在操场上沿一直线排列着 n堆石子.现要将石子有次序地合并成一堆.规定每次只能选相邻的两堆石子合并成新的一堆, 并将新的一堆石子数记为该次合并的得分.允许在第一次合 ...
- HDU4632 Poj2955 括号匹配 整数划分 P1880 [NOI1995]石子合并 区间DP总结
题意:给定一个字符串 输出回文子序列的个数 一个字符也算一个回文 很明显的区间dp 就是要往区间小的压缩! #include<bits/stdc++.h> using namesp ...
- HDU 3506 (环形石子合并)区间dp+四边形优化
Monkey Party Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)Tot ...
- Luogu【P1880】石子合并(环形DP)
先放上luogu的石子合并题目链接 这是一道环形DP题,思想和能量项链很像,在预处理过程中的手法跟乘积最大相像. 用一个m[][]数组来存储石子数量,m[i][j]表示从第 i 堆石子到第 j 堆石子 ...
- 石子合并 区间DP模板题
题目链接:https://vjudge.net/problem/51Nod-1021 题意 N堆石子摆成一条线.现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石 ...
- P1880 [NOI1995]石子合并[环形DP]
题目来源:洛谷 题目描述 在一个圆形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分. 试设计出1个算法,计算出将 ...
- 洛谷 P1080 石子合并 ( 区间DP )
题意 : 在一个圆形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分.试设计出1个算法,计算出将N堆石子合并成1堆 ...
- 石子合并——区间dp
石子合并(3种变形) <1> 题目: 有N堆石子排成一排(n<=100),现要将石子有次序地合并成一堆,规定每次只能选相邻的两堆合并成一堆,并将新的一堆的石子数,记为改次合并的得分, ...
随机推荐
- Twig
{{ dump() }}{{ dump(variable_name) }}List available variables (at top level): {{ dump(_context|keys) ...
- java的排序问题
普通排序 对于基础数据类型的排序,基本只是调用一下方法 如java的 1 Arrays.sort(nums); 那么如何自定义排序规则呢? 自定义排序规则: 假设现在有这么个问题,有n个学生, 每个学 ...
- 将excel按照某一列拆分成多个文件
1.打开目标excel,按alt + f11键打开VBE窗口 2.选择插入->模块粘贴下面代码到编辑器中 Sub 保留表头拆分数据为若干新工作簿() Dim arr, d As Object, ...
- Mybatis拦截器,修改Date类型数据。设置毫秒为0
1:背景 Mysql自动将datetime类型的毫秒数四舍五入,比如代码中传入的Date类型的数据值为 2021.03.31 23:59:59.700 到数据库 2021.04.01 0 ...
- 苹果手机备份及itunes下载更新路径
1.itunes备份路径: C:\Users\xxx.xxx\AppData\Roaming\Apple Computer\MobileSync\Backup\ 2.itunes更新IOS路径: C: ...
- vi 异常退出出现 E325:Attention的解决办法
在linux系统下使用vi编辑程序的时候,没有保存退出,直接关闭了,出现了以下的情况: 打开就会显示filename.c.swap已经存在. 这是因为vi在编辑文件时会创建一个交换文件swap fil ...
- java问题解答
因为子类继承自父类,会沿用父类的东西(没被覆盖的函数以及可见的成员变量等),而这些东西子类是没有的,需要先初始化父类才能被使用 子类构造方法中调用父类构造方法,一个作用是可以给父类构造方法传递实参,给 ...
- 手写reduce()
function reduce(arr, callBack ,initVal){ if(!Array.isArray(arr) || !arr.length || typeof callBack != ...
- python获取报文参考代码
# -*- coding:utf-8 -*- import sys import stomp import logging import time class MyListener(object): ...
- python基于百度unit实现语音识别与语音交互
一.百度Unit新建机器人 网址:https://ai.baidu.com/tech/speech/asr: 1.新建机器人并添加预置技能步骤 (1).新建机器人(添加预置技能),并填写机器人具体信息 ...