【跳石头】
题意:需要移掉尽可能少的石头,使得最近的两个石头距离最远。
思路:枚举会超时,二分答案。
大佬的文章写得非常清楚:https://www.luogu.com.cn/blog/user20197/solution-p2678
1 #include <iostream> 2 3 using namespace std; 4 const int N = 50010; 5 int d[N],n,m; 6 bool check(int x) 7 { 8 int cnt = 0;//计数器(用来和m比较) 9 //这个pre的设置需要注意:不满足时就不用保存,满足时保存当前的下标;如此一来才能满足每次保存的是上一次跳的石头 10 int pre = 0; 11 for(int i = 1; i <= n; i ++) 12 { 13 if(d[i] - d[pre] < x) 14 cnt++; 15 else 16 pre = i; 17 } 18 if(cnt > m) 19 return false; 20 else 21 return true; 22 } 23 int main() 24 { 25 int len,l,r,mid; 26 cin>>len>>n>>m; 27 for(int i = 1; i <= n; i++) 28 { 29 cin >> d[i]; 30 } 31 d[0] = 0;d[n+1] = len;//n+1才是终点的位置 32 l=0;r=len; 33 while(l < r)//二分模板 34 { 35 mid=(l+r+1)/2; 36 if(check(mid)) 37 l = mid; 38 else 39 r = mid-1; 40 } 41 cout<<l<<endl; 42 return 0; 43 }
【进击的奶牛】
题意:(须认真看题qaq)有n个隔间,有c头牛,求最大的相邻隔间距离
思路:二分答案
1 //和前一题的代码差不多都一样 2 #include <iostream> 3 #include<algorithm> 4 using namespace std; 5 const int N = 100010;//看清数据范围 6 int d[N],l,r,n,c,mid; 7 bool check(int x) 8 { 9 int cnt = 0,pre = 0; 10 for(int i = 1; i < n ; i++) 11 { 12 if(d[i]-d[pre] >= x) 13 { 14 cnt++; 15 pre = i; 16 } 17 } 18 if(cnt >= c-1)return true; 19 else return false; 20 } 21 int main() 22 { 23 cin >> n >> c; 24 for(int i = 0;i < n; i ++) 25 cin >> d[i]; 26 sort(d,d+n);//记得排序 27 l = 0; r = d[n-1]; 28 while(l < r) 29 { 30 mid = (l+r+1)/2; 31 if(check(mid)) 32 l = mid; 33 else 34 r = mid - 1; 35 } 36 cout << l <<endl; 37 return 0; 38 }
当你掌握了板子……,每次修改的只有check函数的部分。
【P2440木材加工】
#include <iostream> #include<algorithm> using namespace std; const int N = 100010; int d[N],l,r,n,k,mid; bool check(int x) { int cnt = 0; for(int i = 0; i < n; i ++) { cnt +=(d[i]/x); } if(cnt >= k) return true; else return false; } int main() { long long ans = 0; cin >> n >> k; for(int i = 0; i < n; i ++) { cin >> d[i]; ans +=d[i]; } l = 0; r = ans/k +1;//最好的情况就是每一段都可以全部利用 while(l < r) { mid = (l+r+1)/2; if(check(mid)) l = mid; else r = mid - 1; } cout << l <<endl; return 0; }
【P1873砍树】
1 #include <iostream> 2 #include<algorithm> 3 4 using namespace std; 5 const int N = 1000010;//看清数据范围 6 int d[N],l,r,n,mid; 7 long long k;//看清数据范围 8 bool check(int x) 9 { 10 long long cnt = 0; 11 for(int i = 0; i < n; i ++) 12 { 13 if(x < d[i]) 14 cnt +=(d[i]-x); 15 } 16 if(cnt >= k) 17 return true; 18 else 19 return false; 20 } 21 int main() 22 { 23 int maxn = 0; 24 cin >> n >> k; 25 for(int i = 0; i < n; i ++) 26 { 27 cin >> d[i]; 28 maxn = max(d[i],maxn); 29 } 30 l = 0; 31 r = maxn; 32 while(l < r) 33 { 34 mid = (l+r+1)/2; 35 if(check(mid)) 36 l = mid; 37 else 38 r = mid - 1; 39 } 40 cout << l <<endl; 41 return 0; 42 }