快捷搜索: 王者荣耀 脱发

[luogu-2678]noip2015day2-T1 跳石头 题解

题意解析:题目就是给了你n个在数轴上的点,然后还有起点和终点,坐标分别为0和n,然后去掉最多m个点(除了起点和终点),使剩下的点两两距离的最小值最大。


My opinion:这题唯一的问题是去掉的点不一定要取满m,只需要最后的最小值最大就行了,这时候如果我们知道答案的话,我们就可以判断,这个答案是否可行,而且如果x答案可行,那么x-1一定可行,如果x不可行,x+1一定不可行。所以可以使用二分答案法来寻找答案。 总结: 1、输入。 2、把答案从0到L二分。 3、判断这个答案是否可行。


神奇的代码:

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define rep(i,a,n) for (int i=a;i<=n;i++)
#define per(i,a,n) for (int i=a;i>=n;i--)
#define Clear(a,x) memset(a,x,sizeof(a))
#define ll long long
#define INF 2000000000
#define eps 1e-8
using namespace std;
int read(){
    int x=0,f=1;
    char ch=getchar();
    while (ch<0||ch>9) f=ch==-?-1:f,ch=getchar();
    while (ch>=0&&ch<=9) x=x*10+ch-0,ch=getchar();
    return x*f;
}
const int maxn=50005;
int d[maxn],a[maxn];
int L,n,m;
bool ok(int k){
    int last=0,num=0;
    rep(i,1,n+1){
        if (d[i]-last<k) num++;
            else last=d[i];
        if (num>m) return false; 
    }
    return true;
}
int main(){
    L=read(),n=read(),m=read();
    rep(i,1,n) d[i]=read();
    d[0]=0,d[n+1]=L;
    int l=0,r=L;
    while (l<r){
        int mid=(l+r+1)>>1;
        if (ok(mid)) l=mid;
            else r=mid-1;
    }
    printf("%d
",l);
    return 0;
}
经验分享 程序员 微信小程序 职场和发展