信息学奥赛一本通 1890:【15NOIP提高组】跳石头 | 洛谷 P2678 [NOIP2015 提高组] 跳石头
【題目鏈接】
ybt 1890:【15NOIP提高組】跳石頭
洛谷 P2678 [NOIP2015 提高組] 跳石頭
ybt 1247:河中跳房子
OpenJudge NOI 1.11 10:河中跳房子
(該題與下面兩題是同一題,提交代碼都不用改。)
【題目考點】
1. 二分答案
【解題思路】
將問題抽象:長為L的線段中有N個點,移除M個點,留下N-M個點,將整條線段劃分為N-M+1個線段。求所有可能的劃分方案中,最短線段最長的那種方案下,最短線段的長度。
方案數有CNMC_N^MCNM?種,而M,N達到5?1045*10^45?104,數量級,如果想枚舉所有方案,求每種方案下的最短線段然后求最大值,顯然不可行。
逆向思考,如果給定點之間最小距離x,即點之間的距離必須大于等于x。
需要滿足條件為:看移除M個點的多種方案中,是否存在一種方案其最短線段長度大于等于x
而要判斷該條件是否成立,仍然比較困難。我們可以再逆向思考該命題,將其轉化為:讓每條線段長度都大于等于x,看最少需要移除多少個點
- 如果移除的點的數量小于等于M,則存在一種方案其最短線段長度大于等于x,條件成立。
- 如果移除的點的數量大于M,則不存在這樣的方案,條件不成立。
統計最少移除點數量的方法為:將起點視為觀察點,將距離觀察點x范圍內的點都移除,再將下一個點視為觀察點,將距離它x范圍內的點都移除。重復執行。如果終點也在被移除的范圍內,則應該移除當前觀察點。
清楚要判斷的條件后,這就是一個二分答案求滿足某一條件最大值的問題
求中點:mid = (l+r+1)/2;
如果x滿足條件,下一次x應該更大,取右半邊,l = mid;
如果x不滿足條件,下一次x應該更小,取左半邊,r = mid - 1;
最后得到的結果就是要求的各種方案中最短線段的最大值。
【題解代碼】
解法1:二分答案
#include<bits/stdc++.h> using namespace std; #define N 50005 int len, n, m, d[N];//d[i]:點i到左端的距離 //要判斷:看移除M個點的多種方案中,是否存在一種方案其最短線段長度大于等于x //實際做:讓每條線段長度都大于等于x,看最少需要移除點的數量是否小于等于M bool check(int x) {int ct = 0, p = 0;//p:當前觀察的點的位置 for(int i = 1; i <= n; ++i){if(d[i] - p < x)//如果到當前觀察位置距離小于x,則移除 ct++;else//如果點i到當前觀察的位置的距離大于等于xp = d[i];//則i的位置為當前觀察的位置}if(len - p < x)//如果終點到觀察點距離小于xct++;//移除觀察點return ct <= m;//看移除點的數量是否小于等于M } int main() {cin >> len >> n >> m;for(int i = 1; i <= n; ++i)cin >> d[i];int l = 0, r = len, mid;while(l < r){mid = (l + r + 1) / 2;if(check(mid))l = mid;elser = mid - 1;}cout << l;return 0; }總結
以上是生活随笔為你收集整理的信息学奥赛一本通 1890:【15NOIP提高组】跳石头 | 洛谷 P2678 [NOIP2015 提高组] 跳石头的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java初学者适用项目_有哪些适合jav
- 下一篇: 信息学奥赛一本通 2046:【例5.15