cogs 167. [USACO Mar07] 月度花费

167. [USACO Mar07] 月度花费

★★   输入文件:expense.in   输出文件:expense.out   简单对比
时间限制:1 s   内存限制:128 MB

Farmer John是一个令人惊讶的会计学天才,他已经明白了他可能会花光他的钱,这些钱本来是要维持农场每个月的正常运转的。他已经计算了他以后 N(1<=N<=100,000)个工作日中每一天的花费moneyi(1<=moneyi<=10,000),他想要为他连续 的M(1<=M<=N)个被叫做“清算月”的结帐时期做一个预算,每一个“清算月”包含一个工作日或更多连续的工作日,每一个工作日都仅被包 含在一个“清算月”当中。

FJ的目标是安排这些“清算月”,使得每个清算月的花费中最大的那个花费达到最小,从而来决定他的月度支出限制。

输入

第一行:两个用空格隔开的整数:N和M 第2..N+1行:第i+1行包含FJ在他的第i个工作日的花费

输出

第一行:能够维持每个月农场正常运转的钱数

样例输入

7 5
100
400
300
100
500
101
400

样例输出

500

输入细节

这里有7个工作日来被5个“清算月”划分。他花费100,400,100,500,101,和400元在他的每个工作日。

输出细节

如果FJ安排他的月度预算,他将把前两天划分在一个月中,把第三天、第四天划分在一个月当中,最后的三个工作日各自在一个月当中,所以他一个月最多花费500元,其他的方法总是得出一个较大的结果。

100 400   300 100   500   101   400   每天花费
---1---   ---2---   -3-   -4-   -5-   月度标号
  500       400     500   101   400   月度花费

思路:二分。二分最大值是几,然后进行判断是否合理。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m,num[101000],sum,maxn=-1;
int main(){
    freopen("expense.in","r",stdin);
    freopen("expense.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d",&num[i]);
        sum+=num[i];
        maxn=max(num[i],maxn);
    }
    int l=maxn,r=sum;
    while(l<r){
        int mid=(l+r)/2;
        int ans=0,bns=0;
        for(int i=1;i<=n;i++){
            if(bns+num[i]>mid)    bns=num[i],ans++;
            else    bns+=num[i];
        }
        if(ans<m)    r=mid-1;
        else l=mid+1;
    }
    cout<<l;
}

 

 
posted @ 2017-08-24 11:04  一蓑烟雨任生平  阅读(108)  评论(0编辑  收藏  举报