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 <stdio.h>
#include <stdlib.h>
#include <algorithm>
#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(Sum<mid) // 若距离小于mid,则说明要移开第i个石头
				Count++; // 移开石头数增加
			else{ // 否则 从 第 i 个石头开始重新检验
			
				ans=i; 
			}
		}
		if(Count>m) //若最小移开石头数大于m,则说明该数大了,要减小
			right=mid-1;
		else
			left=mid+1;//否则求出这些数中的最大值
	}
	printf("%d\n",right); //输出最大值
	return 0;
}	


 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值