River Hopscotch POJ - 3258

每年奶牛们都要举办各种特殊版本的跳房子比赛,包括在河里从一块岩石跳到另一块岩石。这项激动人心的活动在一条长长的笔直河道中进行,在起点和距离起点 L 远的终点各有一块岩石 (1 ≤ L ≤ 10^9)。在起点和终点之间,有 N 块岩石 (0 ≤ N ≤ 50000),每块岩石与起点的距离分别为 Di (0 < Di < L)。

在比赛过程中,奶牛轮流从起点出发,尝试到达终点,每一步只能从一块岩石跳到另一块岩石。当然,实力不济的奶牛无法抵达终点,在河中间就退出比赛了。

农夫约翰为他的奶牛们感到自豪并且年年都观看了这项比赛。但随着时间的推移,看着其他农夫的胆小奶牛们在相距很近的岩石之间缓慢前行,他感到非常厌烦。他计划移走一些岩石,使得从起点到终点的过程中,最短的跳跃距离最长,跳到终点的距离不计入。他可以移走除起点和终点外的至多 M 块岩石 (0 ≤ M ≤ N)。

请帮助农夫约翰确定:移走这些岩石后,最短跳跃距离的最大值是多少?

输入

第 1 行包含以单个空格分隔的三个整数 L, N, M。

第 2 到 N + 1 行,每行一个整数,表示每个岩石与起点的距离。不会有两个岩石出现在同一个位置。

输出

输出一个整数,即最短跳跃距离的最大值。

示例输入

25 5 2
2
14
11
21
17

示例输出

4

提示

在移除位于 2 和 14 的两块岩石之后,最短跳跃距离达到了最大值 4 (从 17 到 21,或从 21 到 25)。

题意:给定n个岩石,你要确定移走至多m块岩石使得一头牛最长可能的最短跳跃距离是多少?(有一条河长L,中间N块石头,最多去掉M块,求任意两个石头间最小距离的最大值)

解题思路:二分每次的距离求解。

代码1:

#include <iostream>
#include <algorithm>
#include <string.h>
#include <cstdio>
#include <string>
#include <cmath>
#include <vector>
#include <stack>
#include <queue>
#include <stack>
#include <list>
#include <map>
#include <set>
//#include <unordered_map>
#define Fbo friend bool operator < (node a, node b)
#define mem(a, b) memset(a, b, sizeof(a))
#define FOR(a, b, c) for(int a = b; a <= c; a++)
#define RFOR(a,b, c) for(int a = b; a >= c; a--)
#define sc(a) scanf("%d",&a)
#define off ios::sync_with_stdio(0)
bool check1(int a) { return (a & (a - 1)) == 0 ? true : false; }

using namespace std;
typedef pair<int, int> pii;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const int Maxn = 2e5 + 5;
const double pi = acos(-1.0);
const double eps = 1e-8;

int a[Maxn];
int L,N,M,ans;

int solve(int mid) { 
    int cnt = 0, pos = 0;
    FOR(i, 1, N) {
        if (a[i] - a[pos] < mid) { //两块石头距离小于mid(答案间距)了,移走
            cnt++;
        }
        else pos = i;
    }
    if (cnt > M) { //如果不满足要求
        return 0;
    }
    else 
        return 1;
}

int main() {
    sc(L), sc(N), sc(M);
    FOR(i, 1, N) {
        sc(a[i]);
    }
    a[0] = 0, a[N+1] = L;
    sort(a, a + 2 + N);
    int l = a[0], r = L;
    int ans = 0;
    while (l <= r) {
        int mid = (l + r) >> 1;
        if (solve(mid)) { //满足要求
            l = mid+1; //进一步搜索看能否有更大的最短距离
            ans = mid;//记录答案
        }
        else r = mid-1;//当前的距离不满足题意,往小一点搜索
    }
    printf("%d\n", ans);
}

代码2 :用的是 l=mid和r=mid解

#include <iostream>
#include <algorithm>
#include <string.h>
#include <cstdio>
#include <string>
#include <cmath>
#include <vector>
#include <stack>
#include <queue>
#include <stack>
#include <list>
#include <map>
#include <set>
//#include <unordered_map>
#define Fbo friend bool operator < (node a, node b)
#define mem(a, b) memset(a, b, sizeof(a))
#define FOR(a, b, c) for(int a = b; a <= c; a++)
#define RFOR(a,b, c) for(int a = b; a >= c; a--)
#define sc(a) scanf("%d",&a)
#define off ios::sync_with_stdio(0)
bool check1(int a) { return (a & (a - 1)) == 0 ? true : false; }

using namespace std;
typedef pair<int, int> pii;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const int Maxn = 2e5 + 5;
const double pi = acos(-1.0);
const double eps = 1e-8;

int a[Maxn];
int L,N,M,ans;

int solve(int mid) { 
    int cnt = 0, pos = 0;
    FOR(i, 1, N+1) {
        if (a[i] - a[pos] < mid) { //两块石头距离小于mid(答案间距)了,移走
            cnt++;
        }
        else pos = i;
    }
    if (cnt > M) { //如果不满足要求
        return 0;
    }
    else 
        return 1;
}

int main() {
    sc(L), sc(N), sc(M);
    FOR(i, 1, N) {
        sc(a[i]);
    }
    a[0] = 0, a[N+1] = L;
    sort(a+1, a + 1 + N);
    int l = a[0], r = INF; //注意这里的r一定要开大,不然会WA!!!!!1
    int ans = 0;
    while (r-l>1) {
        int mid = (l + r) >> 1;
        if (solve(mid)) { //满足要求
            l = mid; 
        }
        else r = mid;
    }
    printf("%d\n", l);
}

猜你喜欢

转载自www.cnblogs.com/AlexLINS/p/12642395.html