BZOJ 1650 [Usaco2006 Dec]River Hopscotch 跳石子:二分
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1650
题意:
数轴上有n个石子,第i个石头的坐标为Di,现在要从0跳到L,每次条都从一个石子跳到相邻的下一个石子。
现在FJ允许你移走M个石子,问移走这M个石子后,相邻两个石子距离的最小值的最大值是多少。
题解:
二分。
check函数:
(1)求出每个区间的长度len[i] = dis[i+1] - dis[i]。
(2)对于第1到n-1个区间,如果len[i] > now,则去掉右端点的石头,cnt++。
即:len[i+1]+=len[i]; len[i]=len[i+1];
(3)对于第n个区间,如果len[n] > now,则只能去掉左端点的石头,cnt++。
一旦cnt > m,就return false。
AC Code:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <algorithm> 5 #define MAX_N 50005 6 7 using namespace std; 8 9 int n,m,l; 10 int ans; 11 int dis[MAX_N]; 12 int len[MAX_N]; 13 14 void read() 15 { 16 cin>>l>>n>>m; 17 dis[0]=0; 18 dis[n+1]=l; 19 for(int i=1;i<=n;i++) 20 { 21 cin>>dis[i]; 22 } 23 } 24 25 bool check(int now) 26 { 27 for(int i=0;i<=n;i++) 28 { 29 len[i]=dis[i+1]-dis[i]; 30 } 31 int cnt=0; 32 for(int i=0;i<n;i++) 33 { 34 if(len[i]<now) 35 { 36 len[i+1]+=len[i]; 37 len[i]=len[i+1]; 38 cnt++; 39 if(cnt>m) return false; 40 } 41 } 42 if(len[n]<now && cnt+1>m) return false; 43 return true; 44 } 45 46 void solve() 47 { 48 sort(dis+1,dis+n+1); 49 int lef=1; 50 int rig=l; 51 while(rig-lef>1) 52 { 53 int mid=(lef+rig)/2; 54 if(check(mid)) lef=mid; 55 else rig=mid; 56 } 57 if(check(rig)) ans=rig; 58 else ans=lef; 59 } 60 61 void print() 62 { 63 cout<<ans<<endl; 64 } 65 66 int main() 67 { 68 read(); 69 solve(); 70 print(); 71 }