poj 3273(二分+贪心)

来源:互联网 发布:南极旅游 知乎 编辑:程序博客网 时间:2024/06/07 12:06

题意:

有N天,第i天消耗money_i钱数,现在让你将这N天分成M份,且必须是连续的,求M份中消耗的和的最小值。


解题思路:

二分消耗结果,看是否能分成M份,如果<=M份说明当前和太大,如果>M,份说明和太小,以此作为二分依据。


注意:



#include <string.h>#include <stdio.h>#include <stdlib.h>#define MAXN0 100010#define r1(x) (x)>>1int N,M;int mon[MAXN0],sum;int solve(){    int ans  = 0;    int L,R,Mid;    L = 1,R = sum;    int num,Maxmon,ans1;    ans1 = 0;    bool flag = false;    while(L<R){        Mid = r1(L+R);        ans = mon[0];        num = 1;        Maxmon = mon[0];        for(int i=1;i<N;++i){            if(ans+mon[i]<=Mid){                ans+=mon[i];                if(Maxmon<ans){                    Maxmon = ans;                }                continue;            }            ans = mon[i];            if(Maxmon<ans){                Maxmon = ans;            }            num++;        }        if(num<=M){            if(num==M){                if(!flag){                    ans1 = Maxmon;                    flag = true;                }                else {                    if(ans1>Maxmon){                        ans1 = Maxmon;                    }                }            }            R = Mid;        }        else{            L = Mid+1;        }    }    Maxmon = mon[0];    ans = mon[0];    Mid = L;    for(int i=1;i<N;++i){        if(ans+mon[i]<=Mid){            ans+=mon[i];            if(Maxmon<ans){                Maxmon = ans;            }            continue;        }        ans = mon[i];        if(Maxmon<ans){            Maxmon = ans;        }        //num++;    }    if(flag){        if(ans1>Maxmon){            ans1 = Maxmon;        }    }    else {        ans1  = Maxmon;    }    return ans1;}int main(){    while(scanf("%d%d",&N,&M)!=EOF){        sum = 0;        for(int i=0;i<N;++i){            scanf("%d",&mon[i]);            sum+=mon[i];        }        int ans  = solve();        printf("%d\n",ans);    }    return 0;}


0 0
原创粉丝点击