问题描述
  在一条直线上有n堆石子,每堆有一定的数量,每次可以将两堆相邻的石子合并,合并后放在两堆的中间位置,合并的费用为两堆石子的总数。求把所有石子合并成一堆的最小花费。
输入格式
  输入第一行包含一个整数n,表示石子的堆数。
  接下来一行,包含n个整数,按顺序给出每堆石子的大小 。
输出格式
  输出一个整数,表示合并的最小花费。
样例输入
5
1 2 3 4 5
样例输出
33          //3+6+9+15=33

以下为解题经历:
     第一反应,选择用贪心的思想去解题,因为题中提到只能合并相邻的石子,所以作一些改变,每次选择最小的石子堆,比较其左右两侧的石子,选择与较小的那个合并。
     A[0..len]   取 Min(A)  将A[i] 与 Min(A[i+1],A[i-1]) 合并
     其实此处,带着一些侥幸心理,隐隐觉得不会正确,因为在两两合并的过程中,上一次的合并结果会对下一次的合并造成影响,每一次并非都独立无关。

假如5堆石子,分别为7,6,5,7,100

•按照贪心,合并的过程如下:
      
          7   6   5   7    100  
       7   11.     7    100
       18.         7    100 
          25.              100

总得分=11+18+25+125=179

•另一种合并方案
   
      7    6    5    7    100    
        13.       5     7   100 
        13       12.        100  
        25.                   100

总得分=13+12+25+125=175
————————————————————————————————————
      第二次解题,由于牵扯到不同情况下的不同解,第二反应是符合动态规划的思想,利用一次次的合并过程去更新所得的结果,以便下一次合并使用。
      首先,列出石子 进行观察。A[i]为该堆中的石子个数

1.□  2.□□ 3.□□□ 4.□□□□ 5.□□□□□

1.若石子有1堆,则无需合并,花费为0
     2.若石子有2堆,则合并二者,花费为A[0]+A[1]
     3.若石子有3堆,则有2种情况,①先合并A[0]、A[1]再与A[2]合并 ②先合并A[1]、A[2]再与A[0]合并
     4.若石子有4堆,则有3种情况,...............
     总之,在n堆中,有n-1种情况,而最后一次合并总是以某两堆合成一堆为结果。
     即可将n堆划分成A[0...k] 与 A[k+1...n-1]合并, 
     而A[0...k] 与 A[k+1...n-1]已是最优花费,由各自向下分解所得。
     (递归思想,但由于此次是二维的,即符合动态规划)
————————————————————————————————————
     假设有5堆石子,则A[0...k] 与 A[k+1...n-1]的长度堆数可能为 1、4   2、3   3、2   4、1
     只要其各自已为最优花费。

以上为递推向下的逻辑,在动态规划是由下而上,即5堆石子 需要长度为 2 3 4 的石子最优花费

     如图。

         


     然后开始分析算法过程,首先,最外层循环 控制石子堆长度(len=2 to n),因为只有1堆时无需下续步骤
     接着第二层循环,确定石子堆的起始堆号(i=0 to n-len)即为图中的下划线个数。
     继续分析,发现还需要一层循环控制更新 A[0...k] 与 A[k+1...n-1]的花费price (k=i to j-1)
     确定无遗漏后,开始编写代码过程,如下。
     (注意,花费是每两两合并完的石子数依次相加,所以最后一次合并为合并堆数的总石子量)
——————————————————————————————————————————————、
     由sum[i][j]表示第i堆石子到第j堆石子全部合并的总石子量。dp[i][j]为第i堆石子到第j堆合并的花费(随着动态规划的进行,会越来越越接近最优花费)dp[i][i]=0 (本身无需合并,不需花费)
     即若仅两堆石子合并 则dp[i][j]=dp[i][i]+dp[j][j]+sum[i][j] = 0+0+sum[i][j]

以下用一维sum[n]进行存储,sum[i][j]=sum[j]-sum[i-1] (i!=0),  sum[i][j]=sum[j] (i==0)

——————————————————————————————————————————————
完整代码如下:(时间限制:2.0s   内存限制:256.0MB 情况下只能得90分,一组运行超时)

import java.util.Arrays;
import java.util.Scanner;

public class 合并石子 {

public static void mergeStone(int[][] dp,int[] sum) {
int j=0,temp=0;
for (int i = 0; i < dp.length; i++) {
Arrays.fill(dp[i], Integer.MAX_VALUE);
dp[i][i]=0;
}
for (int len  = 2; len  <= dp.length; len ++) { //划分的石子堆数

for (int i = 0; i < dp.length-len+1; i++) {
j=i+len-1;

for (int k = i; k < j; k++) {
temp=dp[i][k]+dp[k+1][j]+sum[j]-(i==0?0:sum[i-1]);
dp[i][j]=Math.min(dp[i][j], temp);
  //System.out.println(i+","+j+" : "+dp[i][j]);
}
}
}
}
public static void main(String[] args) {

Scanner scam=new Scanner(System.in);
int n=scam.nextInt();
int[] sum=new int[n];
int[][] dp=new int[n][n];
for (int i = 0; i < sum.length; i++) {
if(i==0)
sum[i]=scam.nextInt();
else
sum[i]=sum[i-1]+scam.nextInt();
}
mergeStone(dp,sum);
System.out.println(dp[0][n-1]);
}
}

————————————————————————

石子合并 动态规划(直线型)相关推荐

  1. 算法分析 | 动态规划 | 石子合并问题

    一.问题描述 在一条直线上有n堆石子, 要求每次将相邻的两堆石子合成一堆,花费=两堆石子的总数 求最省总花费. 因为存在相邻的限制条件,不能使用贪心算法将每次最小的2堆合起来.遂使用动态规划 二.代码 ...

  2. 算法提高 合并石子【动态规划】

    问题描述 在一条直线上有n堆石子,每堆有一定的数量,每次可以将两堆相邻的石子合并,合并后放在两堆的中间位置,合并的费用为两堆石子的总数.求把所有石子合并成一堆的最小花费. 输入格式 输入第一行包含一个 ...

  3. 石子合并(动态规划DP)

    时限: 1000ms 内存限制:10000K  总时限:3000ms 描述: 在一个圆形操场的四周摆放着n堆石子(n<= 100),现要将石子有次序地合并成一堆.规定每次只能选取相邻的两堆合并成 ...

  4. 动态规划经典题之石子合并

    题目描述 在一个园形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分 试设计出1个算法,计算出将N堆石子合并成1堆 ...

  5. 石子合并问题java_动态规划求石子合并问题

    1.问题描述 在一个圆形操场的四周摆放着n 堆石子.现要将石子有次序地合并成一堆.规定每次只能选相邻的2 堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分.试设计一个算法,计算出将n堆石子合 ...

  6. 租用游艇问题 石子合并问题 动态规划实验

    实验名称:动态规划 一.实验预习 1.实验目的 1. 理解并掌握动态规划方法的设计思想: 2. 提高应用动态规划方法解决问题和设计算法的能力: 3. 通过编程实现租用游艇问题和石子合并问题,进一步理解 ...

  7. 合并石子(动态规划)

    问题描述: 在一条直线上有n堆石子,每堆有一定的数量,每次可以将两堆相邻的石子合并,合并后放在两堆的中间位置,合并的费用为两堆石子的总数.求把所有石子合并成一堆的最小花费. 输入格式:输入第一行包含一 ...

  8. 【动态规划】小石子游戏-石子合并

    题目 一群小孩子在玩小石子游戏,游戏有两种玩法. (1)路边玩法 有n堆石子堆放在路边,现要将石子有序地合并成一堆,规定每次只能移动相邻的两堆石子合并,合并花费为新合成的一堆石子的数量.求将这N堆石子 ...

  9. 算法基础课-动态规划-区间dp-AcWing 282. 石子合并:区间dp

    文章目录 题目分析 题目链接 题目分析 只能合并相邻两堆.求体力最小值 数据比较弱,最多300堆,每堆重量不超过1000. 状态表示 f[i][j]表示合并区间[i,j]需要的最小体力 状态转移 把区 ...

最新文章

  1. HDU 4540 威威猫系列故事――打地鼠(DP)
  2. with语句和上下文管理器
  3. 能打又实用,推荐8个超实用【神级】在线工具网站,绝对干货
  4. 基于比特币现金的Token逐梦而来
  5. java对象赋值给另一个对象_java面向对象编程
  6. mysql启动提示 access denied for user root@localhost(using password:YES) 解决办法总结
  7. ipad远程连接虚拟机linux,如何从ipad pro上通过SSH远程Linux
  8. 今日恐慌与贪婪指数为61 贪婪程度有所缓解
  9. 支付宝用户可直接签署器官捐献,How about 微信?
  10. Oracle 11g R1(11.1) Joins表连接
  11. ubuntu下,rubyonrails环境搭建
  12. 利用EnableQ服务政府民意调查
  13. 8.docker run --rm
  14. MT6573_android_LCD_backlight_Driver
  15. 微信公众号对话框回复消息链接跳转到小程序界面
  16. upnp 文件服务器,upnp服务器
  17. 五级流水线CPU之低功耗设计 (一) :Bypassing(旁路)
  18. C语言实现双人五子棋
  19. 单片机驱动直流电机c语言代码,单片机驱动带编码器直流电机 源程序
  20. 有扰动的闭环传递函数 matlab,已知闭环传递函数

热门文章

  1. B站apk缓存视频合并批处理
  2. 中缀表达式To前缀表达式 (python实现)
  3. 商用DCLS双核锁步lockstep技术总结
  4. 第2章 时间空间复杂度计算
  5. CC2530的定时/计数器原理与应用
  6. 【一起入门MachineLearning】中科院机器学习-期末题库-【计算题13+简答题3,22+单选题58,82+多选题19】
  7. Linux内核参数值vga的意义,关于传递给Linux内核的vga参数的值的意义
  8. 抓取html对象插件,chrome扩展获取页面dom对象信息
  9. 福建seo,福建seoseo8
  10. vite兼容IE、低版本浏览器方法