二分法初次尝试

//刷二分法的第一道题目,搞懂它搞了3个多小时,恶补了二分法的基础上终于理解了,不容易,欲速则不达,必须具备相应的基础,否则过于生硬。

#include<iostream>
#include<cstdio>
using namespace std;
int a[1000000];
int judge(int mid,int a[],int n,int m)
{
    int i;
    int sum=0;
    int t=1;//这里初值写成了t=0,实际下面的操作中导致了少算了一次。
    for(i=1;i<=n;i++)
    {
        if(a[i]+sum>mid)
        {
            sum=a[i];
            t++;
        }
        else sum=sum+a[i];
    }
    if(t>m)
        return 1;
    else return 0;
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    int i;
    int maxn=0,total=0;
    for(i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        if(a[i]>maxn)
            maxn=a[i];
        total+=a[i];
    }
    int l=maxn;
    int r=total;
    int mid;
    while(l<=r)
    {
        mid=(l+r)/2;
        if(judge(mid,a,n,m))l=mid+1;
        else r=mid-1;
    }
    cout<<l<<endl;//,这里错了,写成了mid这里需要考虑的是最后一次是l与r相等的情况下,下一次就结束了,所以是最后一次了,这时候如果返回的次数正好多余要求的次数即返回1的情况下,
    //我们需要回到正好的状态就是让l+1,这个相当于是一个回溯的操作,即寻找可能性失败后的回退机制,所以这里是输出l,当然如果最后r与l相等的情况下
    //如果返回的仍然是0,这个时候就是最佳状态了,返回mid和l是一样的。(以上分析错误的原因主要是二分法操作不熟练导致,欲速不达,二分法必须熟练掌握才能
    //完全解决各种的子段最少的最大题。)
    return 
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值