蓝桥杯-和并石子--区间DP
来源:互联网 发布:洲际导弹 知乎 编辑:程序博客网 时间:2024/06/05 03:30
在一条直线上有n堆石子,每堆有一定的数量,每次可以将两堆相邻的石子合并,合并后放在两堆的中间位置,合并的费用为两堆石子的总数。求把所有石子合并成一堆的最小花费。
输入格式
输入第一行包含一个整数n,表示石子的堆数。
接下来一行,包含n个整数,按顺序给出每堆石子的大小 。
输出格式
输出一个整数,表示合并的最小花费。
样例输入
5
1 2 3 4 5
样例输出
33
数据规模和约定
1<=n<=1000, 每堆石子至少1颗,最多10000颗。
假如有5堆石头:7 6 5 7 30;
最后合成一堆的石头,肯定是由两堆石头合起来的;a,b两坨;a这坨可能是由原来的1堆,2堆,3堆,4堆合起来的;b坨对应的就是4,3,2,1坨。。
我们需要把这些情况都算出来:并取这四中情况最小的作为选择;
1+4;2+3;3+2;4+1;因为是相邻才能合并;所以1+4和4+1并不是一种情况;可以把1+4理解为a是第一堆,b是第二堆到第五堆。。
怎么算呢?假如是a=1;b=4这种情况;a=1,就是第一坨石头数量嘛:7;b坨又可以分为两坨c,d:1+3;2+2;3+1;
这些情况也需要算出来。。并选出这其中花费最小的组合;
怎么算。。假如c,d是1+3组合;这里c=1;自然是第二堆石头:6;d坨又可能分为e,f:1+2;2+1;算出这两种情况,并选出花费最小的组合;
怎么算!假如e,f为1+2的组合;e为1,即第三堆:5;f为2,自然为1+1;分别为第四堆和第五堆数量了;
用dp[i][j]记录从第i堆合并到第j堆的最小花费
所以需要从底层往上走;先算出两个两个一堆的dp[0][1],dp[1][2],dp[2][3],dp[3][4];
这样才能算三个三个一堆的:dp[0][2]=Min{dp[0][0]+dp[1][2] , dp[0][1],dp[2][2]}; 依次dp[1][3],dp[2][4];
算四个四个同一堆的:dp[0][3]=Min{dp[0][0]+dp[1][3] , dp[0][1]+dp[2][3] , dp[0][2] + dp[3][3]};依次dp[1][4];
最后算5个一堆的!dp[0][4] = Min{dp[0][0]+dp[1][4] , dp[0][1]+dp[2][4] , dp[0][2]+dp[3][4] , dp[0][3]+dp[4][4]};
你看最后的dp[0][4] 是不是就是 1+4;2+3;3+2;4+1;这四种组合选出最小的意思~
状态转移方程:
dp[i][j] = Min{dp[i][k] + dp[k+1][j]} + sum[i][j];(i!=j)(k从i到j-1);
其中sum[i][j]为i到j的石头总量;为啥还有这个?你看状态里不有两堆石头嘛,dp[i][k] ,dp[k+1][j] 这两堆石头合并还要花费啊。
import java.util.Scanner;public class 提高算法合并石子DP {static int sum;public static void main(String[] args) {// TODO Auto-generated method stubScanner input = new Scanner(System.in);int n = input.nextInt();int stone[] = new int[n];int dp[][] = new int[n][n];//dp[i][j]储存从i到j的石头合并需要的最少花费for (int i = 0; i < n; i++) {if (i==0) {stone[i] = input.nextInt();}else {stone[i] = stone[i-1] + input.nextInt();}}for (int i = 0; i < n; i++) {dp[i][i] = 0;//从i到i的石头合并花费为0}for (int l = 2; l <= n; l++) {//遍历每种长度l从2->nfor (int start = 0; start < n-l+1; start++) {//遍历l长度下的每个起点int end = start + l - 1;//对于此时的start对应的终点为enddp[start][end] = Integer.MAX_VALUE;for (int k = start; k < end; k++) {//对于dp[start][end]按k分割,有K中分割方案;if (dp[start][end]>dp[start][k]+dp[k+1][end]) {dp[start][end]=dp[start][k]+dp[k+1][end];//依次比较,取最小的方案;}}//上面部分是分割了两部分;到这了dp[start][end]等于分割到两部分的花费,还需要加上把这两部分合并的花费//也就是从start 到end 的石头数量int sum = 0;if (start==0) {sum = stone[end];}else {sum = stone[end] - stone[start-1];}dp[start][end] += sum;//加上从start到end的石头数量}}System.out.println(dp[0][n-1]);}}
- 蓝桥杯-和并石子--区间DP
- 石子合并 (区间DP)
- 石子合并 (区间dp)
- 石子合并(区间dp)
- <区间DP> 石子合并
- [区间DP]石子合并
- 合并石子,区间DP
- 石子合并【区间dp】
- 区间dp 石子合并
- 石子合并~区间dp基础
- 区间DP-石子合并(线性)
- 石子合并与区间dp
- 石子合并(区间dp)
- 石子合并 (区间DP)
- codevs1048 石子归并(区间DP)
- nyoj+区间dp石子合并
- nyoj737石子合并【区间dp】
- nyoj737 石子合并 区间dp
- 蓝桥杯 垒骰子(矩阵快速幂)
- JVM加载类知识点
- 华为oj中级 字符串运用-密码截取
- 圆形进度条
- log4cplus编译出静态库liblog4cplus.a
- 蓝桥杯-和并石子--区间DP
- 回溯法解决N皇后问题(以四皇后为例)
- Jason Zhang Genting Live Concert Lucky Draw(Concert Lucky Draw, iBET lucky draw, iBET online casino,
- 悲催的 击键项目 ------ quick hit
- (ssl1613)最短路径问题
- 算法训练 Torry的困惑(基本型)
- Unity 获取指定资源目录下的所有文件
- Debian 8 Jessie国内的几个软件源
- Tornado编译vxworks本质及过程