poj 3273 (二分)

题意:按顺序给你N个数,将这N个数分成连续的M段,使得这M段每段的和中的最大值最小,输出最小值。(1<=N<=100000,1<=M<=N,每个数在1到10000之间)

解题思路:不管分成多少段,每种分法和的最大值都在N个数的最大值和N个数的和之间。所求答案也在这之间。

我们可以以此为上下界,二分M段和的最大值进行尝试。对每次二分的值,将数组扫描累加。若当前和大于二分的这个值,则段数加一,由此统计出在当前值下,N个数能够分成的最小段数。若这个段数小于或等于M,则向上界变为mid-1,并记下当前mid的值。否则,下界变为mid+1。继续二分,直到退出循环。最后记录的mid值即为答案。

代码:

#include <stdio.h>

int money[100001];

int main()
{
    int N,M,i,j;
    int sum,count,max;
    int low,high,mid;
    
    
    while(scanf("%d%d",&N,&M)!=EOF)
    {
       sum=0;max = -1;
       for(i = 0;i<N;i++)
       {
             scanf("%d",&money[i]);
             if(money[i]>max)
               max = money[i];
             sum+=money[i];
       }
       low = max;
       high = sum;
       while(low<=high)
       {
          mid = (low+high)/2;
          sum = 0;count = 1;
          for(i = 0;i<N;i++)
          {
            sum+=money[i];
            if(sum>mid)
             {
               sum = money[i];
               count++;
             }     
          }
          if(count<=M)
          {
             max = mid;
             high = mid-1;
          }
          else
          low = mid+1;
       }
       printf("%d\n",max);
    }
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值