Summer Training #12 Div.2 H(区间覆盖+二分)

题目链接

题意:一条线段上有n个点,用线段去覆盖所有点,线段可以不一样长,记其中最长的线段为c,问当所用线段不超过k时,最短的c为多少

题解:将所有点从小到大排序,计算当区间长度为len时,所需的线段数,然后二分长度,直至找到答案。

计算固定区间长度方法,使用贪心求解,置第一个值为区间左端点,从小到大遍历元素,若超过区间长度,则线段数加1,并置当前数为区间左端点,直至所有元素遍历完成。

代码:

#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
#define N 100000
int n,k,hole[N],sum;
bool greedy(int len){
    sum=1;
    int temp=hole[1],i;
    for(i=2;i<=n;i++){
        if(hole[i]-temp>=len){
            temp=hole[i];
            sum++;
        }
    }
    if(sum>k)return false;
    else return true;
}

int greedy2(int l,int r){
    int m=(l+r)>>1;
    if(l==r)return l;
    if(greedy(m)){
        return greedy2(l,m);
    }
    else return greedy2(m+1,r);

}

int main(){
    freopen("C:/Users/fuliujun/Desktop/input.txt","r",stdin);
    freopen("C:/Users/fuliujun/Desktop/output.txt","w",stdout);
    int i,j,T,len;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&k);
        for(i=1;i<=n;i++)
            scanf("%d",&hole[i]);
        len=1;
        while (!greedy(len)){
            len=len<<1;
        }
        int ans=greedy2(len>>1,len);

        printf("%d\n",ans);

    }
    fclose(stdin);
    fclose(stdout);
    return 0;
}
View Code

 

posted @ 2016-07-25 11:14  flowing_water  阅读(155)  评论(0)    收藏  举报