【ZOJ 4062】Plants vs. Zombies

【链接】 我是链接,点我呀:)
【题意】

【题解】


二分最后的最大抵御值mid。
然后对于每个蘑菇。
都能算出来它要浇水几次mid/ai
然后如果第i个蘑菇没浇水达到要求次数。
就在i和i+1之间来回走动(注意改变第i+1个蘑菇的状态)
直到满足每个蘑菇的浇水需求为止。
注意如果到了最后一个蘑菇所在的位置之后。
如果这个蘑菇已经不需要浇水了
那么就没有必要来到第n个位置。直接在n-1位置停下来就ok了

【代码】

#include <bits/stdc++.h>
#define ll long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
using namespace std;

const int N = 1e5;

int n;
ll m;
ll a[N+10];
ll b[N+10];

bool ok(ll mid){
    if (mid==0) return true;
    for (int i = 1;i <= n;i++){
        b[i] = mid/a[i];
        if (mid%a[i]!=0) b[i]++;
    }
    ll cur = m;
    for (int i = 1;i <= n;i++){
        if (i==n && b[i]<=0) return true;
        if (cur<=0) return false;
        cur--;
        if(b[i]>=1){
            b[i]--;
            cur-=(b[i]*2);
            b[i+1]-=b[i];
            if (cur<0) return false;
        }
    }
    return true;
}

int main(){
//  freopen("rush.txt","r",stdin);
    int T;
    scanf("%d",&T);
    while (T--){
        scanf("%d%lld",&n,&m);
        for (int i = 1;i <= n;i++) scanf("%lld",&a[i]);
        ll l = 0,r = 1e17,temp = -1;
        while (l<=r){
            ll mid = (l+r)>>1;
//          printf("%lld\n",mid);
            if (ok(mid)){
                temp = mid;
                l = mid + 1;
            }else{
                r = mid - 1;
            }
        }
        printf("%lld\n",temp);
    }

    return 0;
}

猜你喜欢

转载自www.cnblogs.com/AWCXV/p/9920442.html
ZOJ