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; }