POJ 3258 River Hopscotch

题目大意:

        每年奶牛们都会举办一种特殊的跳房子游戏(通过河中的石头跳跃过河),该河是一条笔直的河,有一块起始石头和一块终点石头,之间的距离是L个单位长度(1 ≤ L ≤ 1,000,000,000),在这两块石头之间还有N块石头(0 ≤ N ≤ 50,000),每头奶牛轮流从起始石头跳跃过河(一块接一块地跳,不能连跳两块或两块以上石头),只有敏捷的牛能顺利渡河,迟钝的都摔倒水里了。农场主John对他的牛很自信,每年都参加这项活动,但是每次都看到其他农场主的牛胆小怯懦的跳着距离很近的石头艰难前行非常无趣,他打算从河里挪去M块石头以增加间距以提高难度(0 ≤ M ≤ N),他知道不能挪走其实和终止的石头,所以只能挪去中间的几块石头。

        现只有一个一个测例,测例中给出L、N和M以及N块石头的每一块到起始石头的距离,现求出挪走M块石头后最小两两石头间距的最大值。

题目链接

注释代码:

/*                                   
 * Problem ID : POJ 3258 River Hopscotch 
 * Author     : Lirx.t.Una                                   
 * Language   : C++                  
 * Run Time   : 125 ms                                   
 * Run Memory : 360 KB                                   
*/

#include <stdlib.h>
#include <stdio.h>

#define	TRUE			1
#define	FALSE			0

//maximum number of rocks
//石头的最大数量
//还包括起始和终点两块石头
#define	MAXROCKN		50002

typedef	int		BOOL;

//location of each rock,每块石头的坐标
//起始石头坐标设为0
int		loc[MAXROCKN];

BOOL
xlim( int d, int m, int end ) {//exceed limits
	//distance,指定的两两石头之间的最小间隔
	//m为指定的挪去石头的数量
	//end为终点石头的数组下标

	//previous and next cursor to the rock
	//前一块访问和当前(即下一块)访问石头的数组下标
	int		pre, nxt;
	//count,记录如果最小距离限制在d时总共可以挪去的石头数量
	int		cnt;

	cnt = 0;
	pre = 0;

	while ( TRUE ) {

		nxt = pre + 1;

		while ( nxt <= end && loc[nxt] - loc[pre] < d ) {
			//若前一块石头和后一块石头的距离不到d则代表需要挪去
			//!!!注意:最后一快石头是不能挪去的,但是如果当
			  //最后一块石头和前一块石头的距离不到d的话就可以挪去
			  //前一块石头(这里并不表示挪去左后一块石头),因为前一块
			  //石头和前前块石头的距离可定大于等于d的
		
			nxt++;
			cnt++;
		}

		if ( nxt > end )
			break;

		//继续向下探索
		pre = nxt;
		nxt = pre + 1;
	}

	if ( cnt > m )//d太大导致挪去的石头过多
		return TRUE;
	else//距离可能刚好可能偏小,表示当前d可以保证挪去m块石头
		return FALSE;
}

int
fcmp(const void *a, const void *b) {

	return *(int *)a - *(int *)b;
}

int
main() {

	int		l, n, m;//首尾两块石头之间的距离、中间石头的个数以及挪去石头的个数
	int		i;
	//[lft, rht]表示最小间距可能的区间
	//mid为区间终点
	//用mid逼近最终答案
	int		lft, rht, mid;
	int		ans;

	scanf("%d%d%d", &l, &n, &m);

	loc[0] = 0;
	loc[n + 1] = l;
	for ( i = 1; i <= n; i++ )
		scanf("%d", loc + i);
	qsort(loc + 1, n, sizeof(int), &fcmp);//将距离从小到大排列以便二分

	//初始化间距的可能区间
	lft = 1;
	rht = loc[n + 1];

	while ( lft <= rht ) {
	
		mid = ( lft + rht ) >> 1;

		if ( !xlim( mid, m, n + 1 ) ) {
			//如果每超出范围则表示间距还可以再大一点
			//但不过得先记录mid的值,因为有可能区间变大一次后
			//就导致之后区间内不存在符合条件的值(都偏大)
			
			ans = mid;
			lft = mid + 1;
		}
		else//否则代表值太大,答案在更小的区间
			rht = mid - 1;
	}

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

	return 0;
}

无注释代码:

#include <stdlib.h>
#include <stdio.h>

#define	TRUE			1
#define	FALSE			0

#define	MAXROCKN		50002

typedef	int		BOOL;

int		loc[MAXROCKN];

BOOL
xlim( int d, int m, int end ) {

	int		pre, nxt;
	int		cnt;

	cnt = 0;
	pre = 0;

	while ( TRUE ) {

		nxt = pre + 1;

		while ( nxt <= end && loc[nxt] - loc[pre] < d ) {
		
			nxt++;
			cnt++;
		}

		if ( nxt > end )
			break;

		pre = nxt;
		nxt = pre + 1;
	}

	if ( cnt > m )
		return TRUE;
	else
		return FALSE;
}

int
fcmp(const void *a, const void *b) {

	return *(int *)a - *(int *)b;
}

int
main() {

	int		l, n, m;
	int		i;
	int		lft, rht, mid;
	int		ans;

	scanf("%d%d%d", &l, &n, &m);

	loc[0] = 0;
	loc[n + 1] = l;
	for ( i = 1; i <= n; i++ )
		scanf("%d", loc + i);
	qsort(loc + 1, n, sizeof(int), &fcmp);
	
	lft = 1;
	rht = loc[n + 1];
	
	while ( lft <= rht ) {
		
		mid = ( lft + rht ) >> 1;
		
		if ( !xlim( mid, m, n + 1 ) ) {
			
			ans = mid;
			lft = mid + 1;
		}
		else
			rht = mid - 1;
	}
	
	printf("%d\n", ans);
	
	return 0;
}

单词解释:

hopscotch:n, 跳房子游戏

event:n, 事件,大事

peculiar:adj, 特殊的,罕见的,奇怪的

version:n, 版本

feature:vt, 以...为特色,以...为主演

involve:vt, 牵扯到,涉及到,包括

excitement:n, 兴奋,刺激,令人兴奋的事

take place:vi, 发生,举行(实现谋划好的)

in turn:adv, 轮流

agile:adj, 敏捷的,机灵的

timid:adj, 胆小的,怯懦的

limp:vi, 跛行,艰难前行

optimal:adj, 最佳的,最理想的

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值