ALDS1_4_D: Allocation

题解
  1. 常规解题思路:让每辆卡车的最大运载量P从0递增,第一个让总运载数v达到n的P就是答案。但是其时间复杂度为O(Pn),会时间超限。
  2. 优化方案:抓住“P增加时v不可能减少”的性质,可以将原来的“从0开始顺序查找P”改造成“二分法查找P”。题目中每个P都对应一个v,而题目要找到第一个达到n的v,也就是查找思想,而这里如果v序列是不减的就可以用二分查找了。
题目
You are given n packages of wi kg from a belt conveyor in order (i=0,1,...n−1). You should load all packages onto k trucks which have the common maximum load P. Each truck can load consecutive packages (more than or equals to zero)from the belt conveyor unless the total weights of the packages in the sequence does not exceed the maximum load P.

Write a program which reads n, k and wi, and reports the minimum value of the maximum load P to load all packages from the belt conveyor.

Input
In the first line, two integers n and k are given separated by a space character. In the following n lines, wi are given respectively.

Output
Print the minimum value of P in a line.

Constraints
1≤n≤100,000
1≤k≤100,000
1≤wi≤10,000

Sample Input 1
5 3
8
1
7
3
9

Sample Output 1
10

If the first truck loads two packages of {8,1}, the second truck loads two packages of {7,3} and the third truck loads a package of {9}, then the minimum value of the maximum load P shall be 10.

Sample Input 2
4 2
1
2
2
6

Sample Output 2
6

If the first truck loads three packages of {1,2,2} and the second truck loads a package of {6}, then the minimum value of the maximum load P shall be 6.
代码块
#include <iostream>
using namespace std;

int n, k;

int Check(int p, int *a)
{
    int j = 0;
    for(int i=0; i<k; i++)
    {
        int s = 0;
        while(s+a[j]<=p)
        {
            s += a[j];
            j++;
            if(j==n)
                return n;
        }
    }
    return j;
}

int main(void)
{
    int i;
    cin>>n>>k;
    int a[n];
    for(i=0; i<n; i++)
        cin>>a[i];
    int left = 0;
    int right = 100000*10000;//P的最大情况即为1辆卡车,100000件重为10000的货物。
    while(left<=right)
    {
        int mid = (left+right)/2;
        if(Check(mid, a)==n && Check(mid-1, a)!=n)
        {
            cout<<mid<<endl;
            break;
        }
        else if(Check(mid, a)==n && Check(mid-1, a)==n)
            right = mid-1;
        else
            left = mid+1;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值