P2678 跳石頭 (二分答案)
阿新 • • 發佈:2020-09-13
題目連結: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 }