AOJ 1359 Wall Clocks
解法
各点から半直線が2本出て,長方形の周上の2点で交わるが,それをそのまま処理すると面倒.
なので,(0, 0) -> (0, d) -> (w, d) -> (w, 0) -> (0, 0) という4辺を展開して,[0, 2(w+d)] という数直線上の区間にしてしまうと楽になる.
半直線は 45度 なので,展開後の座標は簡単な計算により求まる.
各点 i から見える範囲が [li, ri] とすると,ri の 昇順にソートしてやるとよい.最初にどこに時計を置くかを決めれば,あとは時計回り(つまり数直線の右方向)に,置いた時計が見えなくなるまで飛ばして,見えなくなったら追加することで解が得られる.
あとは,最初に時計を置く位置を全探索すれば最適解が求まる.
ソースコード
#include <bits/stdc++.h> using namespace std; using pii = pair<int, int>; int main() { int n, w, d; cin >> n >> w >> d; vector<pii> v; for(int i=0; i<n; ++i) { int x, y; char f; cin >> x >> y >> f; if(f == 'W') { v.emplace_back(x + y, -x + y); } else if(f == 'N') { v.emplace_back(2*d + x - y, x + y); } else if(f == 'E') { v.emplace_back(2*(d+w) - x - y, 2*d + x - y); } else { v.emplace_back(2*(d+w) - x + y ,2*(d+w) - x - y); } } sort(v.begin(), v.end()); int L = 2*(w + d); int res = 1e9; for(int i=0; i<n; ++i) { auto tmp = v; for(int j=i-1; j>=0; --j) { if(tmp[j].first < tmp[i].first) { tmp[j].first += L; tmp[j].second += L; } } sort(tmp.begin(), tmp.end()); int cnt = 1; int now = tmp[0].first; for(int j=0; j<n; ++j) { if(tmp[j].second > now) { now = tmp[j].first; cnt++; } } res = min(res, cnt); } cout << res << endl; }