POJ 3273 Monthly Expense(二分)

Monthly Expense

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.

Input

Line 1: Two space-separated integers: N and M Lines 2… N+1: Line i+1
contains the number of dollars Farmer John spends on the ith day

Output

Line 1: The smallest possible monthly limit Farmer John can afford to
live with.

Sample Input
7 5
100
400
300
100
500
101
400
Sample Output
500
Hint
If Farmer John schedules the months so that the first two days are a month, the third and fourth are a month, and the last three are their own months, he spends at most $500 in any month. Any other method of scheduling gives a larger minimum monthly limit.

题意:
给你一个含有N个元素的序列,你要将这个序列切割成M个子序列(序列必须是连续的),使得每一个子序列的和不超过X,让你求最小的X
思路:
用二分法枚举X,二分函数里面的话就是枚举出最长的不大于X的最长序列,同时记录序列的个数,如果子序列的个数大于让你切的序列的话肯定就是不符合的了,但是如果是小于的话肯定是符合的,因为一些子序列还可以在进行分割

#include
#include
#include
#include
#include
#include
#include
#define ll long long
using namespace std;
const int inf=0x3f3f3f3f;
int v[100005],s[50005];
int n,m;
bool tp(int mid)
{
    int sum=1,x=0;
    for(int a=1;a<=n;a++)
    {

        if(x+v[a]<=mid)
        {
            x+=v[a];
        }
        else
        {
            sum++;
            x=v[a];
        }
        if(sum>m)
            return false;
    }
    return true;
}
int  main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        int sum=0,l=0;
        for(int a=1;a<=n;a++)
        {
            scanf("%d",&v[a]);
            sum+=v[a];
            l=max(l,v[a]);
        }
        int r=sum,mid;
        while(l<=r)
        {

            mid=(l+r)/2;
            if(tp(mid))
            {
                r=mid-1;
            }
            else
            {
                l=mid+1;
            }
        }

        printf("%d\n",(l+r+1)/2);
    }
    return 0;
}

你可能感兴趣的:(#,【尺取,二分,三分】)