二分优化的暴力枚举

#include<stdio.h>
int a[100005];
int main(void)
{
    int n,m,r,l;
	int sum;
	int teams;
	int max,min;
	int i,j;
	int mid;
	scanf("%d%d",&n,&m);        //输入n个物品和m个人
    for(i = 1;i <= n;i ++){     //输入n个物品各自的重量,依次序赋值,并保存总重量sum备用
        scanf("%d",&a[i]);
        sum += a[i];
    }
    r = sum;                    //将总数默认为最大生气值的默认值(实际是不是可能的)
    l = 0;                      //将0作为最小生气的人的生气值(从这里的开始计算)
                                //找到的最大值的控制开关
    while(r-l > 1){             //如果最大值和最小时之间相差小于1,则认为已找到最优解
        mid=(l + r)/2;          //算出中间值(缩小范围,中间的情况也是如此,没必要重复)
        sum = 0;                //用以记录各个值间的大小大概关系
        teams = 1;
        for(i = 1;i <= n;i ++){
            if(sum + a[i] <= mid)sum += a[i];//最开始时,各值不够大,让他们相加好了
            else{        //相加到一定程度后,转换另外一种算法,把他的值降小,重新计算
                sum = a[i];
                if(sum > mid){   //如果这个值远远大于中间值,则基本上他就是最大值了,
                        //但亦不排除后面会有值比此大,因此未用break语句</a>; 而是赋予开关一个很大的值
                    teams = 10000000;
                }
                teams ++;         //开关加1,证明大于平均值的生气值又多了一个
            }
        }
        if(teams > m)l = mid;//生气值大于中间值的人数已大于总人数,也就是说大家可以再上一台阶
        else if(teams <= m)r = mid;  //否则,大家应当降一个级别,将中间值赋予最大值
        }
    printf("%d\n",r);
    return 0;
}

这种题型有几个特点: 1.连续 2.平均中求最小,最大 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值