LeetCode 1000. 合并石头的最低成本

该博客介绍了一种解决LeetCode上1000题目的算法,即求解最小合并石头的成本。博主通过区间动态规划的方法,详细解释了如何计算不同长度区间内合并石头的最小花费,并给出了C#代码实现。主要思路包括判断区间长度是否小于K、等于K以及大于K时的处理方式,以及如何递归地找到最优分割方案。
摘要由CSDN通过智能技术生成

题目连接:https://leetcode-cn.com/problems/minimum-cost-to-merge-stones/

在这里插入图片描述

思路:区间动态规划,详细看注释

DP[s, e]1.如果区间长度小于K则为0
2.如果区间长度等于K则为区间中所有数字的和
3.如果区间长度大于K则为合并到数量小于K后的最小花费
using System;
using System.Collections.Generic;
using System.Text;

namespace LeetCode {
    class Program_1000 {
        int Step;
        //前缀和
        int[] Sum = new int[32];
        //DP数组
        int[,] DP = new int[32, 32];

        /// <summary>
        /// 区间动态规划
        /// </summary>
        /// <param name="s">区间起点</param>
        /// <param name="e">区间终点</param>
        /// <returns></returns>
        public int DfsDP(int s, int e) {
            if (int.MaxValue != DP[s, e]) {
                //动态规划, 已经计算过的
                return DP[s, e];
            }
            if (e - s + 1 < Step) {
                //长度不够,花费0
                DP[s, e] = 0;
                return DP[s, e];
            }
            if (e - s == Step - 1) {
                //长度刚刚好,合并计算花费
                DP[s, e] = Sum[e + 1] - Sum[s];
                return DP[s, e];
            }
            //当前区间需要合并的次数
            int needMerge = (e - s) / (Step - 1);
            if (0 == (e - s) % (Step - 1)) {
                //减去本层的1次合并,获得分割后两个子层中需要合并的次数和
                needMerge--;
            }
            //将区间分成两个,获得花费最小的分割方案
            for (int i = s; i < e; i++) {
                //左区间可以合并的次数
                int mergeCount = (i - s) / (Step - 1);
                //加上右区间需要合并的次数
                mergeCount += (e - i - 1) / (Step - 1);
                if (mergeCount < needMerge) {
                    //合并次数不够,分割方案不合法
                    continue;
                }
                DP[s, e] = Math.Min(DP[s, e], DfsDP(s, i) + DfsDP(i + 1, e));
            }
            if (0 == (e - s) % (Step - 1)) {
                //区间合并成一堆
                DP[s, e] += (Sum[e + 1] - Sum[s]);
            }
            return DP[s, e];
        }

        public int MergeStones(int[] stones, int K) {
            if (0 != (stones.Length - 1) % (K - 1)) {
                return -1;
            }
            Step = K;
            Sum[0] = stones[0];
            for (int i = 1; i <= stones.Length; i++) {
                Sum[i] = Sum[i - 1] + stones[i - 1];
            }
            for (int i = 0; i < stones.Length; i++) {
                for (int k = 0; k < stones.Length; k++) {
                    DP[i, k] = (i == k) ? 0 : int.MaxValue;
                }
            }
            return DfsDP(0, stones.Length - 1);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

achonor

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值