leetcode---每日一题:1011. 在 D 天内送达包裹的能力

1011. 在 D 天内送达包裹的能力

传送带上的包裹必须在 D 天内从一个港口运送到另一个港口。

传送带上的第 i 个包裹的重量为 weights[i]。每一天,我们都会按给出重量的顺序往传送带上装载包裹。我们装载的重量不会超过船的最大运载重量。

返回能在 D 天内将传送带上的所有包裹送达的船的最低运载能力。
示例 1:

输入:weights = [1,2,3,4,5,6,7,8,9,10], D = 5
输出:15
解释:
船舶最低载重 15 就能够在 5 天内送达所有包裹,如下所示:
第 1 天:1, 2, 3, 4, 5
第 2 天:6, 7
第 3 天:8
第 4 天:9
第 5 天:10

请注意,货物必须按照给定的顺序装运,因此使用载重能力为 14 的船舶并将包装分成 (2, 3, 4, 5), (1, 6, 7), (8), (9), (10) 是不允许的。 
示例 2:

输入:weights = [3,2,2,4,1,4], D = 3
输出:6
解释:
船舶最低载重 6 就能够在 3 天内送达所有包裹,如下所示:
第 1 天:3, 2
第 2 天:2, 4
第 3 天:1, 4
示例 3:

输入:weights = [1,2,3,1,1], D = 4
输出:3
解释:
第 1 天:1
第 2 天:2
第 3 天:3
第 4 天:1, 1

题解

二分查找不好理解可以自己画图理解

class Solution {
public:
    int shipWithinDays(vector<int>& weights, int D) {
        // 真的想不到,很精妙
        // 贪心算法加二分查找
        /* 
            依据: 存在一个运载能力的最小值x当运载能力大于x时肯定没问题,当运载能力低于x时候肯定不行,那么这个x就是我们所求的答案

            接下来就有两个问题,能解决这两个问题就能用二分查找进行解决
            问题一: 怎么确定二分查找的上下边界
            问题二: 怎么确定x运载能力的时候能够运完

            问题一: 运送能力最低:也就是一个物体运送一天也就是max(weights[i])  运送能力最高:一天运完 sum(weights[i])
            问题二: 因为只能够按照顺序运送,所以可以用贪心算法,贪心策略就是每次运送运载能力内的最多的货
        
         */

        int left=0,right=0;

        for(int i=0; i<weights.size();i++) {
            left=max(left,weights[i]);
            right+=weights[i];
        }


        int mid=0;
        // 左闭右闭
        while(right>left) {
            mid = left+(right-left)/2;
            // cout<<"mid "<<mid<<" ";
            if(Check_ability(weights,mid,D)) {
                right=mid;
                // cout<<"true"<<endl;
            } else {
                left=mid+1;
                // cout<<"false"<<endl;
            }
        }

        return right;




    }



    bool Check_ability(const vector<int>& weights , int ability ,int D) {

        int index=0;
        for(int i=0 ; i<=D ; i++) { // 为什么要等于D因为可能再最后一天装好了,所以要多一次进行验证
            if(index>=weights.size()) {
                return true;
            }
            int sum=0;
            for(index; index<weights.size();index++) {
                sum+=weights[index];
                if(sum>ability) {
                    // index--;// 因为break后就没有++操作了  || 这时候index就是下一段的起点
                    break;
                }
            }
            // cout<<"index: "<<index<<endl;
        }

        return false;

    }
    
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值