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 }

 

posted @ 2020-09-12 22:37  不敢说的梦  阅读(166)  评论(0)    收藏  举报