Monthly Expense POJ - 3273(二分)

Farmer John is an astounding accounting wizard and has realized he might run out of money to run the farm. He has already calculated and recorded the exact amount of money (1 ≤ moneyi ≤ 10,000) that he will need to spend each day over the next N (1 ≤ N ≤ 100,000) days.

FJ wants to create a budget for a sequential set of exactly M (1 ≤ M ≤ N) fiscal periods called “fajomonths”. Each of these fajomonths contains a set of 1 or more consecutive days. Every day is contained in exactly one fajomonth.

FJ’s goal is to arrange the fajomonths so as to minimize the expenses of the fajomonth with the highest spending and thus determine his monthly spending limit.
输入
第1行:两个以空格分隔的整数: N和 M
行2 … N +1:行 i +1包含农夫约翰第i天 花费的数量
输出
第1行:Farmer John可以承受的最低月限额。
样本输入
7 5
100
400
300
100
500
101
400
样本输出
500
提示
如果Farmer John安排这几个月,前两天是一个月,第三个和第四个是一个月,最后三个是他们自己的月份,他在任何一个月花费最多500美元。任何其他调度方法都会给出较大的最小月限

题意:

m个月内,每个月可以包含任意多个花费,共有n个花费,找一个最小的每月最大花费,

思路:

1.我们二分最大花费,然后遍历n个花费;
2.用cnt记录该mid需要多少月,k记录花费,当k加上该花费后当月的花费要大于当前的mid时 (因为遍历的是最大花费),该花费不能加到当前月,而是加到下一月中,此时记录的月份cnt++;
3.遍历完之后,如果当前的mid需要的月份cnt>m个月,说明该mid偏大,反之偏小;
4.二分的上下界:下界可以是所有花费中的最大值(因为每个月至少包含一次花费),上界可以是n个花费加起来(因为最大的情况就是一个月包含了所有花费);

#include<stdio.h>
#include<algorithm>
#include<string.h>
#define ll long long
#define PI  3.14159265358979323846
#pragma GCC optimize(2)
using namespace std;
const ll maxn=1e5+7;
const int INF=1e9+7;
const double esp=1e-6;
ll price[maxn];
int main()
{
    ll n,m;
    scanf("%lld%lld",&n,&m);
    ll l=-INF,sum=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&price[i]);
        sum+=price[i];
        l=max(l,price[i]);
    }
    ll r=sum;
    ll mid;
    while(r-l>=0)
    {
        mid=(l+r)>>1;
        ll cnt=1;
        ll k=0;
        for(int i=1;i<=n;i++)
        {
           if(k+price[i]<=mid)
                k+=price[i];
           else
           {
               cnt++;
               k=price[i];					//这里wa了几次,因为没有把超过的花费加到下一个月中;
           }
        }
        if(cnt>m)
        l=mid+1;
        else
        r=mid-1;
    }
    printf("%lld\n",l);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值