poj 3273 Monthly Expense(二分)

呃,通过这题有深入的理解了一下二分查找的神奇。。。

题意是:给你n天和每天需要花的钱,让你把这些天分成m份,每份都是连续的一天或几天,要求每份的和尽量小,输出这个和。二分的上界为所以钱的总数,下界为每天所花钱的最大值,然后二分查找到最适合的mid。但是,却为此WA了无数次啊~~,悲催啊·····

恩,还是举个例子来说吧,10 10 3 10 4 1 9 6 8 8 10 5 6,这一组数据,如果你用二分的查找mid值的话,可能会输出13,但是这题的答案是14,因为你找不到一个整数正好符合搜索条件,但是如果是14的,最后的5和6可以是一组,也可以是两组,前面的其他的已经符合了,即,14的话,可以这样分组10 , 10 3 , 10 4, 1 9 , 6 8 , 8 , 10 , 5 6,也可以如下分组:10 , 10 3 , 10 4 ,1 9 ,6 8 , 8 , 10 , 5 ,6。而如果是13的话,最少的组数是10 ,10  3, 10, 4 1, 9, 6 , 8 ,8 ,10, 5 6  ,所以答案应该是14;

讲的不是很明白,可以看下我的代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int v[100005];

int main()
{
    int n , m , s , e , mid , sx , x , i;

    while (scanf("%d%d",&n,&m) != EOF)
    {
        s = e = 0;
        for (i = 0; i < n ; i++)
        {
            scanf("%d", &v[i]);
            if (v[i] > s)
            s = v[i];
            e += v[i];
        }

        while (s < e)
        {
            mid = (s + e) / 2;
            x = 0;sx = 0;
            for (i = 0 ;i < n; i++)
            {
                x += v[i];
                if(x > mid)
                {
                    sx++;
                    x = v[i];
                }
            }
            if (sx < m)
            e = mid;
            else
            s = mid + 1;
        }
        printf ("%d\n", mid);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/misty1/p/2485601.html