BZOJ1639: [Usaco2007 Mar]Monthly Expense 月度开支

【传送门:BZOJ1639


简要题意:

  约翰刷了N 次信用卡,第i次刷掉了Ai 元。银行告诉他可以在接下来的M个月里分期还清这 些债务,但是先发生的债务必须先偿还,也不能把一笔债务分在两个月里还。约翰想找到一种方法,使得每个月还的钱尽量均匀。请问,约翰应该在每个月还多少债务,才能使他在所有月份中的最大还款数额最小?


输入格式:

  • 第一行:两个整数N 和M,1 ≤ M ≤ N ≤ 100000

  • 第二行到第N + 1 行:第i + 1 行有一个整数Ai,1 ≤ Ai ≤ 10000


输出格式:

  • 单个整数:表示最大还款额的最小值


样例输入:

7 5

100

400

300

100

500

101

400


样例输出:

500


样例解释:

  前两笔放在第一个月,第三和第四笔放在第 二个月,最后三笔各自放在一个月


题解:

  二分答案判断

  二分最大还款项的最小值,判断是否能够符合分成的月份小于等于m,并且得到的值小于二分的答案


参考代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
using namespace std;
int a[110000];
int s[110000];int n,m;
bool check(int x)
{
    int len=1,d=0;
    for(int i=1;i<=n;i++)
    {
        if(a[i]>x) return false;
        if(d+a[i]>x)
        {
            len++;d=a[i];
            if(len>m) return false;
        }
        else d+=a[i];
    }
    return true;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    int l=0,r=1000000000;
    int ans=0;
    while(l<=r)
    {
        int mid=(l+r)/2;
        if(check(mid)==true)
        {
            ans=mid;
            r=mid-1;
        }
        else l=mid+1;
    }
    printf("%d
",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/Never-mind/p/7761669.html