1. 程式人生 > >BZOJ 1650 [Usaco2006 Dec]River Hopscotch 跳石子:二分

BZOJ 1650 [Usaco2006 Dec]River Hopscotch 跳石子:二分

code amp using names ref www bsp problem ans

題目鏈接: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 }

BZOJ 1650 [Usaco2006 Dec]River Hopscotch 跳石子:二分