#include<cstdio> #include<iostream> using namespace std; int a[50010],L,m,n; int check(int x){ int p=0,ans=0;//p为前一个石头到指向石头的距离的下标 for(int i=1;i<=n;i++){ if(a[i]-a[p]<x){//如果第i个石头到前一个石头的距离小于假设的答案 ans++; //该石头可以搬走 } else{//如果大于(即满足条件) p=i;//则保留该石头,并将p记录该石头的下标以便计算下一个石头到它的距离 } } return ans<=m; } int main(){ scanf("%d%d%d",&L,&n,&m); for(int i=1;i<=n;i++){ scanf("%d",a+i); } a[++n]=L;//我们假设在终点处有第n+1个石头,则他到起点的距离为L int l=1,r=L+1;//r要注意+1,下面二分可能搜不到右端点 while(l+1<r){ int mid=(l+r)/2; if(check(mid)) l=mid;//说明二分结果小了,要向右二分 else r=mid;//说明结果大了,要向左二分 } printf("%d ",l); return 0; }
重新写了一遍,印象更深
#include<cstdio> using namespace std; #define N 100010 int n,m,len,d[N]; bool check(int x){ int res=0,p=0; for(int i=1;i<=n;i++){ if(d[i]-p<=x) res++; else p=d[i]; } return res<=m; } int main(){ scanf("%d%d%d",&len,&n,&m); for(int i=1;i<=n;i++) scanf("%d",&d[i]); int l=1,r=len,mid; while(l<r){ mid=(l+r>>1); if(check(mid)) l=mid+1; else r=mid; } printf("%d",l); return 0; }