AOJ 1194: バンパイア / Vampire

,

http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1194

整数点ちょうどのところだけ見るのではだめ。

solution

各整数$n \in [-r, +r]$について少しずれた位置$x = n \pm \epsilon \in (-r, +r)$を見ればよい。 そのような点ごとにその位置を太陽が始めて照らす時間を求め、その最小値を答える。 $O( r)$。

implementation

#include <cmath>
#include <cstdio>
#include <vector>
#define repeat(i, n) for (int i = 0; (i) < int(n); ++(i))
#define repeat_from(i, m, n) for (int i = (m); (i) < int(n); ++(i))
using namespace std;
template <class T> inline void setmax(T & a, T const & b) { a = max(a, b); }
template <class T> inline void setmin(T & a, T const & b) { a = min(a, b); }

int main() {
    while (true) {
        int r, n; scanf("%d%d", &r, &n);
        if (r == 0 and n == 0) break;
        vector<int> hl(2*r);
        vector<int> hr(2*r);
        repeat (i, n) {
            int xl, xr, hi; scanf("%d%d%d", &xl, &xr, &hi);
            repeat_from (x, max(-r, xl), min(+r, xr)-1+1) setmax(hr[r  +x], hi);
            repeat_from (x, max(-r, xl)+1, min(+r, xr)+1) setmax(hl[r-1+x], hi);
        }
        double t = INFINITY;
        repeat_from (x, -r, +r+1) {
            double y = sqrt(r*r - x*x);
            if (x < +r) setmin(t, r - y + hr[r  +x]);
            if (-r < x) setmin(t, r - y + hl[r-1+x]);
        }
        printf("%.8lf\n", t);
    }
    return 0;
}