poj3258

题目较难。题目大致题意为母牛要过河,起始位置为0,终止位置为L,中间有n个石头,在可以移开最多m(0<=m<=n)块石头的情况下,求最大的(石块间的最小距离)。

题目与poj3273相似。可对照poj3273结题报告分析,分析如下:

选定一个数x,按照任意石头之间距离不小于(即>=)x的原则分组(结合贪心算法分组),求得最小石头移开数。

1)若最小石头移开数大于m,则说明该数大了,要减小。

2)若最小石头移开数小于等于m,则说明满足题意。那么我们就求以求出这些数中最大的x

而x的范围为0——L,且f(x)单调递增,f(x)表示对于给定的最小间隔,最小石头移开数。故可以利用二分查找法求得满足f(x)<=m的最大x。

下面是程序: 328K+94MS

#include 
#include 
#include 
#define Max 50010 // 最大个数
using namespace std;
int record[Max]; // 记录石头的位置
int L,n,m;
int main(){
	scanf("%d%d%d",&L,&n,&m);
	record[0]=0; // 起始位置为0
	record[n+1]=L; // 结束位置为L
	for(int i=1;i<=n;i++) // 输入石头位置
		scanf("%d",&record[i]);
	sort(record+1,record+1+n); //对石头位置进行升序排序
	int left=0,right=L,mid; //0<=x<=L,二分法求解满足最少石头移开数f(x)<=m的最大x值
	while(left<=right){
		mid=(left+right)>>1;
		int ans=0,Sum,Count=0;
                   // ans,Sum,Count依次表示从哪个石头开始检查、第i个石头与第ans个石头之间的距离、移开石头个数
                  for(int i=1;i<=n+1;i++){ // 贪心法求解对于给定的x,按照上述组合方式所需移开的最小石头个数,注意这里i循环到n+1,而不是n(想想为什么)
			Sum=record[i]-record[ans];
			if(Summ) //若最小移开石头数大于m,则说明该数大了,要减小
			right=mid-1;
		else
			left=mid+1;//否则求出这些数中的最大值
	}
	printf("%d\n",right); //输出最大值
	return 0;
}	


 

 

你可能感兴趣的:(acm)