[NOIP2015] 跳石头 (二分)
题解
L的数据为10的九次方所以DP肯定是过不了的,可以考虑二分跳跃的距离。
这个ll和rr就是查找答案的范围的左边界和右边界,二分距离。我们要找到一个最大值的距离,这个距离能保证只搬走m或m以内个石头就能让任意两个相邻的石头之间的距离大于等于这个距离。我们就来二分查找满足这个条件的最大的距离。先是从0到L之间查找答案,二分取中间值L/2,然后看这个距离是否满足上面那个条件,如果满足条件,就把二分查找的左边界调到mid+1,然后再次查找。如果中间值不满足条件,所以就把查找的右边界调到mid-1去。直到区间查找完毕,输出答案。
#include<stdio.h> #include<math.h> #include<algorithm> using namespace std; int ll=1000000000,rr,mid; int a[50005]; int main() { int l,m,n,x,stone,ans; scanf("%d%d%d",&l,&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } a[n+1]=l; rr=l;ll=0; while(ll<=rr) { mid=(rr+ll)/2; x=0;stone=0; for(int i=1;i<=n;i++) { if(a[i]-a[x]<mid)//距离太小需要搬石头 { stone++; if(stone>m)break; } else x=i; } if(stone>m)rr=mid-1;//搬得太多 需要开大距离 else ll=mid+1,ans=mid; } printf("%d",ans); return 0; }