ADV-1175 打包(二分)

问题描述

  Lazy有N个礼物需要打成M个包裹,邮寄给M个人,这些礼物虽然很便宜,但是很重。Lazy希望每个人得到的礼物的编号都是连续的。为了避免支付高昂的超重费,他还希望让包裹的最大重量最小。

输入格式

  一行两个整数N和M。
  一行N个整数,表示N个礼物的重量。

输出格式

  一个整数,表示最小的最大重量。

数据规模和约定

  N, M <= 100,000
  重量 <= 1,000

思路

最大值最小,先看看能不能二分
二分包裹的重量,二分的区间是[所有重量的最大值,所有重量之和],设答案为x,大于x的重量一定能打包成M份,重量小于x的不能打包成M份,具有二段性

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 100010;
int w[N];
int n, m;

bool check(int x)
{
    int val = 0, cnt = 1;
    for(int i = 1; i <= n; i ++ )
    {
        val += w[i];
        if(val > x) // 超过当前包裹的最大重量了,就新增一个包裹
        {
            cnt ++;
            val = w[i];
        }
        if(cnt > m) return false;  // 包裹的数量大于需要打包的数量
    }
    return true;
}

int main()
{
    cin >> n >> m;
    int maxv = -1, sum = 0;
    for(int i = 1; i <= n; i ++ )
    {
        scanf("%d", &w[i]);
        maxv = max(maxv, w[i]);
        sum += w[i];
    }
    
    int l = maxv, r = sum; // 二分的区间
    while(l < r)
    {
        int mid = l + r >> 1;
        if(check(mid))  r = mid;
        else    l = mid + 1;
    }
    cout << l;
    return 0;
}
posted @ 2022-03-04 20:29  inss!w!  阅读(84)  评论(0编辑  收藏  举报