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; }

浙公网安备 33010602011771号