【ZOJ 4062】Plants vs. Zombies

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

【题解】

二分最后的最大抵御值mid。 然后对于每个蘑菇。 都能算出来它要浇水几次mid/a[i](上取整) 然后如果第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;
}
posted @ 2018-11-07 08:23  AWCXV  阅读(223)  评论(0编辑  收藏  举报