• 算法笔记_083:蓝桥杯练习 合并石子(Java)


    目录

    1 问题描述

    2 解决方案

     


    1 问题描述

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

     


    2 解决方案

    本题主要考查动态规划法思想。

    刚开始做的时候,使用贪心法求解,即每次选择相邻两个和为最小的一组合成堆,结果评分为10分,后来仔细想了一下,贪心法不能达到最优解,唯有使用动态规划法求解。

    该题几乎和训练题集中的矩阵相乘一样,具体思想讲解,请参考本人另一篇博客:算法笔记_081:蓝桥杯练习 算法提高 矩阵乘法(Java)

     

    具体代码如下:

    import java.util.Scanner;
    
    public class Main {
        
        public long getSum(long[] A, int a, int b) {
            long sum = 0;
            for(int i = a;i <= b;i++)
                sum += A[i];
            return sum;
        }
        
        public void printResult(long[] A) {
            if(A.length == 1) {
                System.out.println(A[0]);
                return;
            }
            long[][] dp = new long[A.length + 1][A.length + 1];
            for(int len = 2;len <= A.length;len++) {
                for(int i = 1, j = len;j <= A.length;i++,j++) {
                    long min = Long.MAX_VALUE;
                    for(int k = i;k < j;k++) {
                        if(min > dp[i][k] + dp[k + 1][j] + getSum(A, i - 1, j - 1))
                            min = dp[i][k] + dp[k + 1][j] + getSum(A, i - 1, j - 1);
                    }
                    dp[i][j] = min;
                }
            }
            System.out.println(dp[1][A.length]);
            return;
        }
        
        public static void main(String[] args) {
            Main test = new Main();
            Scanner in = new Scanner(System.in);
            int n = in.nextInt();
            if(n < 1 || n > 1000)
                return;
            long[] A = new long[n];
            for(int i = 0;i < n;i++) {
                A[i] = in.nextLong();
            }
            test.printResult(A);
        }
    }
  • 相关阅读:
    mdx 根据维度Hierarchy节点的名字来filter节点,搜索节点
    学习C++.Primer.Plus 8 函数探幽
    学习C++.Primer.Plus 7 函数
    学习C++.Primer.Plus 6 分支语句和逻辑操作符
    学习C++.Primer.Plus 5 循环和关系表达式
    学习C++.Primer.Plus 4 复合类型
    NYoj_171聪明的kk
    NYoj_104最大和
    希尔排序
    NYoj_49开心的小明
  • 原文地址:https://www.cnblogs.com/liuzhen1995/p/6561915.html
Copyright © 2020-2023  润新知