【每日一题Day47】LC1687从仓库到码头运输箱子 | 动态规划

简介: 思路:首先我们要尽可能在一趟行程中搬运更多的箱子,一趟行程可以搬运的最多箱子由箱子的个数、箱子的重量以及箱子的目的地决定

从仓库到码头运输箱子【LC1687】


你有一辆货运卡车,你需要用这一辆车把一些箱子从仓库运送到码头。这辆卡车每次运输有 箱子数目的限制 总重量的限制 。


给你一个箱子数组 boxes 和三个整数 portsCount, maxBoxes 和 maxWeight ,其中 boxes[i] = [portsi, weighti] 。


  • portsi 表示第 i 个箱子需要送达的码头, weightsi 是第 i 个箱子的重量。
  • portsCount 是码头的数目。
  • maxBoxes 和 maxWeight 分别是卡车每趟运输箱子数目和重量的限制。


箱子需要按照 数组顺序 运输,同时每次运输需要遵循以下步骤:


  • 卡车从 boxes 队列中按顺序取出若干个箱子,但不能违反 maxBoxes 和 maxWeight 限制。


  • 对于在卡车上的箱子,我们需要 按顺序 处理它们,卡车会通过 一趟行程 将最前面的箱子送到目的地码头并卸货。如果卡车已经在对应的码头,那么不需要 额外行程 ,箱子也会立马被卸货。


  • 卡车上所有箱子都被卸货后,卡车需要 一趟行程 回到仓库,从箱子队列里再取出一些箱子。


卡车在将所有箱子运输并卸货后,最后必须回到仓库。


请你返回将所有箱子送到相应码头的 最少行程 次数。


2022/12/05

啊啊啊 没时间做了 打了一天工 然后晚上给室友过生日啦 好高兴 以后再也没有这样好的室友啦 请一天假 sososorry

2022/12/06

我觉得把最普通的dp写出来就不错了 超时不是我的问题是数据的问题…


  • 思路:首先我们要尽可能在一趟行程中搬运更多的箱子,一趟行程可以搬运的最多箱子由箱子的个数、箱子的重量以及箱子的目的地决定


  • 动态规划【超时】


  • 思路:首先我们要尽可能在一次运送中搬运更多的箱子,一次运送可以搬运的最多箱子由箱子的个数、箱子的重量以及箱子的目的地决定,如果想要一次性运送第i个至第j个箱子,那么必须满足箱子总个数小于maxBoxes、总重量小于maxWeight,那么运送这些箱子所需要的行程数为相邻两个箱子目的地不相等的次数。每运送一次货物还需要一趟行程返回仓库,因此还需要一趟行程,最后返回总共需要的最少行程数即可


。使用前缀和的方式快速计算第i个至第j个箱子的重量weight以及相邻两个箱子目的地不相同的个数diff


。使用动态规划的方法计算运送所有箱子需要的最少行程数


  • 实现:为了方便描述i ii的下标从1开始,指代boxes数组下标为i−1的箱子j 的下标从0开始


前缀和


。weight[i]:表示前i个箱子的重量总和


  • 第i 个到第j 个箱子的重量为:weight[j]−weight[i]


。diff[i]:表示前i个箱子中相邻两个箱子目的地不同的个数


  • 第i个到第j 个箱子中相邻两个箱子目的地不相等的次数为:diff[j]−diff[i]


动态规划


1.确定dp数组(dp table)以及下标的含义


dp[i]:运送前i个箱子需要的最少行程数


2.确定递推公式


对于第i个箱子,需要枚举上次一运送的最后一个箱子j,那么这次需要运送的箱子为[j+1,i],首先需要判断箱子重量和箱子个数是否满足要求,如果满足要求才可以一次性从仓库装入卡车,然后才可以通过diff和dp数组得到运送至对应的码头所需要的行程数。


因此dp公式为


dp[i]=min(dp[i],dp[j]+diff[i]−diff[j+1]+2)


所需要满足的条件为


0≤j

i−j≤maxBoxes

weights[i]−weights[j]≤maxWeights


3.如何初始化


。dp[0]=0;

。其他设置为最大值


4.确定遍历顺序


由dp公式可知,外层正序遍历行i,内层正序遍历列j


5.举例推导dp数组


  • 代码


class Solution {
    public int boxDelivering(int[][] boxes, int portsCount, int maxBoxes, int maxWeight){
        int n = boxes.length;
        int[] weights = new int[n + 1];
        int[] diff = new int[n + 1];
        int[] dp = new int [n + 1];
        for (int i = 0; i < n; i++){
            weights[i + 1] = weights[i] + boxes[i][1];
            if ( i > 0 && boxes[i - 1][0] != boxes[i][0]){
                diff[i + 1] = diff[i] + 1;
            }else{
                diff[i + 1] = diff[i];
            }
        }
        for (int i = 1; i <= n; i++){
            dp[i] = Integer.MAX_VALUE;
            for (int j = 0; j < i; j++){
                if (i - j <= maxBoxes && weights[i] - weights[j] <= maxWeight){
                    dp[i] = Math.min(dp[i],dp[j] + diff[i] - diff[j + 1] + 2);
                }
            }
        }
        return dp[n];
    }
}


。复杂度


  • 时间复杂度:O(n 2 ),n为箱子个数
  • 空间复杂度:O ( n 2 )


动态规划+单调队列


  • 优化思路:不想优化了!!!!


目录
相关文章
|
4月前
一文搞懂:【bzoj】3436小K的农场
一文搞懂:【bzoj】3436小K的农场
20 0
|
5月前
|
Java 测试技术
HDU-1233-还是畅通工程
HDU-1233-还是畅通工程
32 0
|
5月前
【错题集-编程题】过河卒(动态规划-路径问题)
【错题集-编程题】过河卒(动态规划-路径问题)
|
5月前
|
算法 测试技术 C#
【线段树】【前缀和】:1687从仓库到码头运输箱子
【线段树】【前缀和】:1687从仓库到码头运输箱子
|
10月前
|
机器学习/深度学习 算法 测试技术
C++前缀和算法的应用:从仓库到码头运输箱子原理、源码、测试用例
C++前缀和算法的应用:从仓库到码头运输箱子原理、源码、测试用例
|
算法
【过河卒】回溯算法保姆式解题
【过河卒】回溯算法保姆式解题
90 0
|
测试技术
Leecode 42. 接雨水
Leecode 42. 接雨水
91 1
畅通工程 HDU - 1232
畅通工程 HDU - 1232
74 0
7-9 地下迷宫探索 (8 分)
7-9 地下迷宫探索 (8 分)
139 0
7-9 地下迷宫探索 (8 分)
|
存储 算法 Java
第十二届蓝桥杯A组省赛填空题Java思路及代码合集(相乘直线货物摆放路径回路计数)
第十二届蓝桥杯A组省赛填空题Java思路及代码合集(相乘直线货物摆放路径回路计数)
272 0