题意:简单的说就是给你一段长度,在这一段中给出m个点,然后在这m个点中选出k个点,让这k个点之间相邻两个点的之间距离的最小值最大
思路:通过二分枚举这个最小值,然后通过贪心的思想找出满足要求的最大的这个最小值
#include<stdio.h>
#include<algorithm>
#define N 100005
int a[N],n,m;
bool greed(int k) //判断当前找到的这个最小值
{
int s=a[0],i,count=0;
for(i=1;i<n;i++)
{
if(a[i]-s>=k)
{
count++;
s=a[i];
}
if(count>=m-1) //当前找到的最小值偏小或恰好成立,可以再往偏大的地方找
return true;
}
return false; //找到当前的最小值偏大,需要再往偏小的地方找
}
void binary_search() //通过二分找这个最小值
{
int x=0,y=a[n-1]-a[0],mid;
while(x<=y)
{
mid=(x+y)/2;
if(greed(mid))
x=mid+1;
else
y=mid-1;
}
printf("%d\n",x-1); //当二分结束的时候,就可以找到这个最大的最小值
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
std::sort(a,a+n);
binary_search();
}
return 0;
}
题意:简单的说就是给你一段长度,在这一段中给出m个点,然后在这m个点中选出k个点,让这k个点之间相邻两个点的之间距离的最大值最小(与上一题的不同点)
思路:通过二分枚举这个最小值,然后通过贪心的思想找出满足要求的最小的这个最大值
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int L,n,m,count1,p;
int a[500005];
bool greed(int x)
{
int s=0,i;
count1=0;
for(i=0;i<=n;i++)
{
if(a[i]-s<=x)
{
while(a[i]-s<=x&&i<=n) //贪心思想,找出当前最大值能包含的最多的相邻段
i++;
s=a[--i];
count1++;
}
}
if(count1<=m) //找到的当前最大值恰好或偏大,如果之前没有确定左端点,此处会出错(找到的最大值偏小的话会一直减小)
return true;
return false;
}
void binary_search()
{
int l=p,r=a[n],mid;
while(l<=r)
{
mid=(l+r)/2;
if(greed(mid))
r=mid-1;
else
l=mid+1;
}
printf("%d\n",r+1);
}
int main()
{
int i;
while(~scanf("%d%d%d",&L,&n,&m))
{
p=0;
for(i=0;i<n;i++)
scanf("%d",&a[i]);
a[n]=L;
sort(a,a+n+1);
for(i=1;i<=n;i++)
if(p<a[i]-a[i-1])
p=a[i]-a[i-1]; //找到二分的左端点(很关键),此处wa了好几次
binary_search();
}
return 0;
}