程序设计:植物大战僵尸(计蒜客-----蓝桥杯模拟二)

题解:思路很奇妙,不太好想。

这道题可以通过二分来解决,每次要么往左移动要么往右移动,反正不可以不动。假设二分到答案x,那么

对arr[i]这个数,我们至少要来x%arr[i] ?  x/arr[i]+1 : x/arr[i]这么多次,所以说我们可以通过左右移动来不断的来使得arr[i]达到要求,当来arr[i] a次时,必须去arr[i+1] 或者说arr[i-1] a-1次,这里(我们处理为都右->左->右->左)。也就是说当我们来arr[i]   a次时,arr[i+1]来了a-1次。所以当为们考虑第i个位置时,当完成第i-1个位置时已经帮arr[i]完成了一部分....具体实现看代码吧:

#include<bits/stdc++.h>
using namespace std;
const long long  N=1e5+7;
long long  arr[N];
long long  num[N];
long long  n,m;
bool check(long long  x){
    long long  tmp=0;
    long long  tmpnext=0;
    long long  sum=0;
    for(long long  i=1;i<=n;i++){
        tmp=x/arr[i];
        if(x%arr[i]) tmp++;
        tmp-=tmpnext;//这里的tmpext还没有更新,所以表示的是在完成i-1的时候完成i的部分。
        if(tmp<=0) {//说明第i个点在第i-1的时候已经被完成了。
            if(i!=n) tmp=1;//每次都得移动一个
            else tmp=0;//到达n了,并且n也满足了,怎么着都无所谓了
            tmpnext=0;
        }
        else  tmpnext=tmp-1;
        sum+=tmp+tmpnext;
        if(sum>m) return false;
    }
    return 1;
}
int main(){
    cin>>n>>m;
    for(long long  i=1;i<=n;i++)
        cin>>arr[i];
    long long  l=0;
    long long  r=1e18+7;
    long long  ans=0;
    while(l<=r){
        long long  mid=(r+l)/2;
        if(check(mid)){
            l=mid+1;
            ans=max(ans,mid);
        }
        else r=mid-1;
    }
    cout<<ans<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/Accepting/p/13819512.html