1. 程式人生 > >ZOJ 4062 Plants vs. Zombies(二分答案)

ZOJ 4062 Plants vs. Zombies(二分答案)

題目連結:Plants vs. Zombies

題意:從1到n每個位置一棵植物,植物每澆水一次,增加ai高度。人的初始位置為0,人每次能往左或往右走一步,走到哪個位置就澆水一次。求m步走完後最低高度的植物最大高度為多少。

題解:明顯二分答案的題目。check時從左往右遍歷,貪心思路:把該位置滿足同時給後面減少澆水次數,策略是該位置和後一個位置左右橫跳,注意最後一個的時候,如果滿足就不需要再跳過去。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4
#include <algorithm> 5 using namespace std; 6 7 const int N=1e5+10; 8 typedef long long ll; 9 ll a[N],d[N],n,m; 10 11 bool check(ll k){ 12 for(ll i=1;i<=n;i++) d[i]=0; 13 ll cnt=m; 14 for(ll i=1;i<=n;i++){ 15 if(cnt==0){ 16 if(i==n&&d[i]>=k) return
true; 17 return false; 18 } 19 cnt--; 20 d[i]+=a[i]; 21 if(d[i]<k){ 22 ll tmp=k-d[i]; 23 ll c=tmp/a[i]; 24 if(tmp%a[i]!=0) c++; 25 if(cnt>=2*c){ 26 cnt-=2*c; 27 d[i]+=(a[i]*c);
28 d[i+1]+=(a[i+1])*c; 29 } 30 else return false; 31 } 32 } 33 return true; 34 } 35 36 int main(){ 37 int t; 38 scanf("%d",&t); 39 40 while(t--){ 41 ll ans=0; 42 scanf("%lld%lld",&n,&m); 43 for(ll i=1;i<=n;i++){ 44 scanf("%lld",&a[i]); 45 } 46 ll l=0,r=1e17+100; 47 while(l<=r){ 48 ll mid=(l+r)/2; 49 if(check(mid)) ans=max(ans,mid),l=mid+1; 50 else r=mid-1; 51 } 52 printf("%lld\n",ans); 53 } 54 55 return 0; 56 }
Code