009:月度开销

Posted MalcolmMeng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了009:月度开销相关的知识,希望对你有一定的参考价值。

描述

农夫约翰是一个精明的会计师。他意识到自己可能没有足够的钱来维持农场的运转了。他计算出并记录下了接下来 N (1 ≤ N ≤ 100,000) 天里每天需要的开销。

约翰打算为连续的M (1 ≤ M ≤ N) 个财政周期创建预算案,他把一个财政周期命名为fajo月。每个fajo月包含一天或连续的多天,每天被恰好包含在一个fajo月里。

约翰的目标是合理安排每个fajo月包含的天数,使得开销最多的fajo月的开销尽可能少。

 

输入第一行包含两个整数N,M,用单个空格隔开。
接下来N行,每行包含一个1到10000之间的整数,按顺序给出接下来N天里每天的开销。输出一个整数,即最大月度开销的最小值。样例输入

7 5
100
400
300
100
500
101
400

样例输出

500

提示若约翰将前两天作为一个月,第三、四两天作为一个月,最后三天每天作为一个月,则最大月度开销为500。其他任何分配方案都会比这个值更大。

WA:

技术分享图片
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
#include<map>
#include<cstring>
#define DEBUG(x) cout << #x << " = " << x << endl
using namespace std;
const int MAXN=1e5+10;
int N,M;
int dayConsume[MAXN];
int feasible(int n)
{
    int ptr=0;
    int minCnt=0;
    while(ptr<N){
        int sum=0;
        while(true){
            sum+=dayConsume[ptr];
            if(sum>n)break;
            else ptr++;
        }
        minCnt++;
    }
    return cnt-M;
}
int BinSearch(int lb,int rb)
{
    int lastPos=1<<30;
    while(lb<=rb){
        int mid=lb+(rb-lb)/2;
        int t=feasible(mid);
        if(t>0){
            lb=mid+1;
        }
        else if(t<0){
            rb=mid-1;
        }
        else {
            if(mid<lastPos){
                lastPos=mid;
                rb=mid-1;
            }
            else {
                lb=mid+1;
            }
        }
    }
    return lastPos;
}
int main()
{
    freopen("in.txt","r",stdin);
    scanf("%d %d",&N,&M);
    int lb=0;
    int rb=0;
    for(int i=0;i<N;i++){
        int t;
        scanf("%d",&t);
        dayConsume[i]=t;
        rb+=t;
        lb=lb<t?t:lb;
    }
    printf("%d",BinSearch(lb,rb));
    return 0;
}
View Code

AC:

技术分享图片
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
#include<map>
#include<cstring>
#define DEBUG(x) cout << #x << " = " << x << endl
using namespace std;
const int MAXN=1e5+10;
int dayConsume[MAXN];
int N,M;
bool isValid(int n)
{
    int m=1;///1?为什么是1
    int curCost=0;
    for(int i=0;i<N;i++){
        if(dayConsume[i]>n)return false;
        if(curCost+dayConsume[i]>n){
            m++;
            curCost=dayConsume[i];
            if(m>M)return false;
        }
        else {
            curCost+=dayConsume[i];
        }
    }
    return true;
}
int BinSearch(int lb,int rb)
{
    int lastPos=-1;
    while(lb<=rb){
        int mid=lb+(rb-lb)/2;
        if(isValid(mid)){
            lastPos=mid;
            rb=mid-1;
        }
        else {
            lb=mid+1;
        }
    }
    return lastPos;
}
int main()
{
//    freopen("in.txt","r",stdin);
    scanf("%d %d",&N,&M);
    int lb=1<<30,rb=0;
    for(int i=0;i<N;i++){
        scanf("%d",&dayConsume[i]);
        int t=dayConsume[i];
        rb+=t;
        lb=min(lb,t);///?为什么不是max
    }
    printf("%d
",BinSearch(lb,rb));
    return 0;
}
View Code

WA和AC两份代码,后者更加符合二分的特点。AC代码是用true或false来标定条件是否成立,WA的代码是用返回值的正负是否为零作为判断依据。


以上是关于009:月度开销的主要内容,如果未能解决你的问题,请参考以下文章

月度开销

06:月度开销

bzoj 1639 月度开销

使用从循环内的代码片段中提取的函数避免代码冗余/计算开销

实习月度总结2018-10

如何正确绘制月度销售数据?