题目大意:
每年奶牛们都会举办一种特殊的跳房子游戏(通过河中的石头跳跃过河),该河是一条笔直的河,有一块起始石头和一块终点石头,之间的距离是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, 最佳的,最理想的