Openjudge NOI題庫 ch0111/10 河中跳房子|NOIP2015 day2 stone


這題同時也是NOIP2015 D2T1 跳石頭 stone 原題。

 

總時間限制:
1000ms
內存限制:
65536kB
描述

每年奶牛們都要舉辦各種特殊版本的跳房子比賽,包括在河里從一個岩石跳到另一個岩石。這項激動人心的活動在一條長長的筆直河道中進行,在起點和離起點L遠 (1 ≤ L≤ 1,000,000,000) 的終點處均有一個岩石。在起點和終點之間,有N (0 ≤ N ≤ 50,000) 個岩石,每個岩石與起點的距離分別為Di (0 < Di < L)。

在比賽過程中,奶牛輪流從起點出發,嘗試到達終點,每一步只能從一個岩石跳到另一個岩石。當然,實力不濟的奶牛是沒有辦法完成目標的。

農夫約翰為他的奶牛們感到自豪並且年年都觀看了這項比賽。但隨着時間的推移,看着其他農夫的膽小奶牛們在相距很近的岩石之間緩慢前行,他感到非常厭煩。他計划移走一些岩石,使得從起點到終點的過程中,最短的跳躍距離最長。他可以移走除起點和終點外的至多M (0 ≤ MN) 個岩石。

請幫助約翰確定移走這些岩石后,最長可能的最短跳躍距離是多少?

 

輸入
第一行包含三個整數L, N, M,相鄰兩個整數之間用單個空格隔開。
接下來N行,每行一個整數,表示每個岩石與起點的距離。岩石按與起點距離從近到遠給出,且不會有兩個岩石出現在同一個位置。
輸出
一個整數,最長可能的最短跳躍距離。
樣例輸入
25 5 2
2
11
14
17
21
樣例輸出
4
提示
在移除位於2和14的兩個岩石之后,最短跳躍距離為4(從17到21或從21到25)。

 

 1 #include <stdio.h>
 2 int river[50020];
 3 int main()
 4 {
 5     int l,r,n,m;
 6     int i,j,mid;
 7     int ans;
 8     scanf("%d%d%d",&ll,&n,&m);
 9     for(i=1;i<=n;i++)
10         scanf("%d",&river[i]);
11     river[0]=0;
12     river[n+1]=ll;
13     l=0;
14     r=ll+1;
15     while(l+1<r)
16     {
17         mid=(l+r)/2;
18         ans=0;
19         i=0;
20         while(i<=n)
21         {
22             j=i+1;
23             while(river[j]-river[i]<mid&&j<=n+1)
24                 j++;
25             ans+=j-i-1;//因為算的是間距,所以還要-1 
26             i=j;
27         }
28         if(ans<=m) l=mid;
29         else r=mid; 
30     }
31     printf("%d\n",l);
32     return 0;
33 }

 

這題二分的思路是這樣的:

先存好全部石頭數據

然后用二分取一個最長的最短跳躍距離,即mid

當選出一對石頭j與i,它們之間的距離>=mid,就把它們中間的石頭算作移除,移除數量就是j-i-1

移除之后,從石頭j開始,繼續往后算,除非算到了n+1,自然就不能繼續算下去了

算完之后,用總移除數ans對比實際可以移除的石頭數m

  當ans<m,說明取的mid間距太短,導致某些石頭間的距離大於mid時無法移除石頭,所以l=mid

  當ans==m,別急,也許某些石塊移除后,兩塊石頭的距離比mid大,說明mid可能還是小了,所以l=mid

  當ans>m,說明取的mid太長,導致本來對某對石頭進行移除操作就合適的時候還繼續往下找,所以r=mid

最后l==r,輸出l

 

可以舉一個極端的例子說明ans與m的比較

假設石頭是這樣的:

0                        20 23 26 29 31                             51 (r=52)

只允許移除3塊石頭。這樣的情況下自然是移除中間3塊石頭,不然最短距離將會是3或是6。

設mid為(0+52)/2=26,則會移除20、23兩塊石頭,再移除29、31兩塊石頭,ans>m,r=mid=26

mid=(0+26)/2=13,則20與0空移除一次,再移除23、26、29、31,同理r=mid=13

mid=(0+13)/2=6,則先空移除,然后移除23,移除29,31與51空移除,ans<m,l=mid=6

mid=(6+13)/2=9,移除23、26、31。ans==m了,就行了嗎?不,明顯20與29距離是9,還可以更長為11,那就加長試試,l=9

mid=(9+13)/2=11,移除23、26、29。此時還不能確定11就是最優解,因為還有12,所以l=11

mid=12,移除了23、26、29、31,所以r=12

mid=11,又區間是[l,r)左閉右開型的,即現在能確定距離就是mid=l=11了。

 

Ps 做了這么多二分,果然中值賦值條件是難點所在啊!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM