ZOJ4062 Plants vs Zombies(二分)

题意:

有一排植物,初始高度是0。机器人从坐标轴0处出发,最多走k步,每走过一株植物,该植物的能量增加i(i为植物的坐标)。问怎么安排机器人的路线使得植物中最少的能量最大,并输出那个值。

题解:

二分查找,枚举所有可能的能量值。

每次check,先计算以x为最小值的情况下,每个位置至少要走几步。

然后模拟一边机器人浇水的过程看能否实现。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
typedef long long ll;
int T;
int N; 
ll m;
ll a[maxn],b[maxn];
int check (ll x) {
    ll step=0;
    for (int i=0;i<N;i++) {
        //先算一遍以x为最小值的情况下,每个位置至少要走多少步
        b[i]=(x+a[i]-1)/a[i]; 
    } 
    for (int i=0;i<N-1;i++) {
        step++;//每走到一个位置就加一步 
        b[i]--;
        if (b[i]<=0) continue;
        step+=2*b[i];
        //每次想要再走一遍当前位置的话,必然是继续往前走再走回来,需要两倍的步数
        b[i+1]-=b[i];//因为b[i]的步数剪掉
        if (step>m) return 0; 
    } 
    if (b[N-1]>0) {
        step++;
        b[N-1]--;
        step+=b[N-1]*2;
    }
    if (step>m) return 0;
    return 1;
}

int main () {
    scanf("%d",&T);
    while (T--) {
        scanf("%d%lld",&N,&m);
        for (int i=0;i<N;i++)
            scanf("%lld",&a[i]);
        ll l=0,r=1e12+10;
        ll ans=0;
        while (l<r) {
            ll mid=(l+r)>>1;
            if (check(mid)) {
                ans=mid;
                l=mid+1;
            }
            else r=mid;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/zhanglichen/p/12505944.html