1. 程式人生 > 實用技巧 >P2678 跳石頭 (二分答案)

P2678 跳石頭 (二分答案)

題目連結:P2678

解題思路:

如果可行解為單調,則可以用二分答案找到最終答案,對於選到的答案,去驗證是否正確,最後確定所需解。

AC程式碼:

 1 #include <cstdio>
 2 #include <iostream>
 3 #define ll long long
 4 using namespace std;
 5 ll l,n,m,d[50010],t[50010];
 6 bool judge(ll x) // 判斷該解是否合適
 7 {
 8     ll s = 0;
 9     for(ll i = 1; i <= n; i++) t[i] = d[i];
10 for(ll i = 1; i <= n; i++) 11 { 12 if(t[i]-t[i-1] < x) 13 { 14 t[i] = t[i-1]; // 搬石頭時可以將前一個值複製到現在的值,實現O(1)的操作 15 s++; 16 } 17 } 18 if(s > m) return false; 19 else return true; 20 } 21 ll bfind(ll l, ll r) 22 { 23 ll mid;
24 while(r-l > 1) // r-l = 1時,有可能會死迴圈 25 { 26 mid = (r-l)/2+l; 27 if(judge(mid)) l = mid; // judge判斷是否正確,然後左右區間調整 28 else r = mid-1; 29 } 30 if(judge(r)) return r; 31 else return l; 32 } 33 int main() 34 { 35 cin >> l >> n >> m; 36 for
(ll i = 1; i <= n; i++) cin >> d[i]; 37 cout << bfind(1,l); 38 return 0; 39 }