UVa 11627 - Slalom 二分. oj错误题目 难度: 0

题目

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2674


题意

有严格下降的n条线段,长度都为w,第i条线段起点xi,终点xi + w,高度yi,现在有s种垂直恒定速度可以选择,水平速度不能超过vh,问要经过每条线段,垂直恒定速度最大可以选择什么

 

思路

明显,二分枚举速度speed

第一条线段因为是起点所以肯定都能到达

对于第i条线段,从第i-1条线段出发落到i条线段相同高度所用时间为t = (yi - y_{i - 1}) / speed,设能到达的区域为[xlefttruei, xrighttruei],能到达的区域为[xlefttrue_{i-1}- vh * t, xrighttrue_{i-1} + vh * t]与自身线段[xi, xi + w]的交集,如果不存在这个交集,就代表落不到这个线段上。

 

感想:

现在uva无法通过,包括他人题解注明已通过的也不行

 

代码

#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <string>
#include <tuple>
#define LOCAL_DEBUG
using namespace std;
const int MAXN = 1e5 + 5;
const int MAXS = 1e6 + 6;
long long xleft[MAXN];
long long y[MAXN];
long long w, vh;
int n, s;
long long xlefttrue[MAXN], xrighttrue[MAXN];
int speeds[MAXS];
bool check(int speed) {
    xlefttrue[0] = xleft[0] * speed;
    xrighttrue[0] = (xleft[0] + w) * speed;
    for (int i = 1; i < n; i++) {
        long long t = (y[i] - y[i - 1]);
        xlefttrue[i] = max(xleft[i] * speed, xlefttrue[i - 1] - t * vh);
        xrighttrue[i] = min((xleft[i] + w) * speed, xrighttrue[i - 1] + t * vh);
        if (xlefttrue[i] > xrighttrue[i])return false;
    }
    return true;
}

int main() {
#ifdef LOCAL_DEBUG
    freopen("C:\\Users\\Iris\\source\\repos\\ACM\\ACM\\input.txt", "r", stdin);
    //freopen("C:\\Users\\Iris\\source\\repos\\ACM\\ACM\\output.txt", "w", stdout);
#endif // LOCAL_DEBUG
    int T;
    cin >> T;
    for (int ti = 1;ti <= T; ti++) {
        cin >> w >> vh >> n;
        for (int i = 0; i < n; i++) {
            cin >> xleft[i] >> y[i];
        }
        cin >> s;
        for (int i = 0; i < s; i++) {
            cin >> speeds[i];
        }
        sort(speeds, speeds + s);
        int lind = 0, rind = s;
        if (!check(speeds[lind]))cout << "IMPOSSIBLE" <<endl;
        else {
            while (lind < rind) {
                int mid = (lind + rind) >> 1;
                if (mid == lind)break;
                if (check(speeds[mid])) {
                    lind = mid;
                }
                else {
                    rind = mid;
                }
            }
            cout << speeds[lind] << endl;
        }
    }

    return 0;
}
View Code

 

posted @ 2019-03-04 15:18  雪溯  阅读(170)  评论(0编辑  收藏  举报