ABC107-C:Candles(300)
問題
https://beta.atcoder.jp/contests/abc107/tasks/arc101_a
数直線上に N つの点が与えられる。今地点 0 にいる。数直線上の点から K 個選ぶとき、移動距離の最小値を求めよ。
考え方
(i)正負に分けて全探索
最短距離を動くときの点の選び方は正の方向から i の点を選び、負の方向から k - i を選ぶ。 i, k - i を全探索すれば良い。正と負で List を分けてしまうのが楽。正または負の方向から何もとらないというパターンがあるので 0 を add しておく必要がある。
public void solve(int testNumber, InputReader in, PrintWriter out) { int n = in.nextInt(), k = in.nextInt(); List<Long> plus = new ArrayList<>(); List<Long> minus = new ArrayList<>(); for (int i = 0; i < n; i++) { long x = in.nextLong(); if (x < 0) { minus.add(-x); } else if (x == 0) { k--; } else if (x > 0) { plus.add(x); } } plus.add(0L); minus.add(0L); Collections.sort(plus); Collections.sort(minus); long ans = LINF; for (int i = 0; i < plus.size(); i++) { int j = k - i; if (0 <= j && j < minus.size()) { long min = min(plus.get(i), minus.get(k-i)); long max = max(plus.get(i), minus.get(k-i)); ans = min(ans, min*2 + max); } } for (int i = 0; i < minus.size(); i++) { int j = k - i; if (0 <= j && j < plus.size()) { long min = min(minus.get(i), plus.get(k-i)); long max = max(minus.get(i), plus.get(k-i)); ans = min(ans, min*2 + max); } } out.println(ans); }
((ii)区間を全探索
最短距離を選ぶとき、選ぶ k つの点は連続している。よって k のとり方を全探索すれば良い。具体的には区間 [l, l+k-1] を全探索する。その時のパターンとしては
(A) (x[l] が負、) x[l+k-1] が負
⇒移動距離は負の方向の最大値なので x[l]
(B) x[l] が負、x[l+k-1] が正
⇒移動距離は負の方向と正の方向の合算。正または負の移動距離の小さい値で折り返す。
(C) x[l] が正 (、x[l+k-1] が正)
⇒移動距離は正の方向の最大値なので x[l+k-1]
という3パターンがありうる。
public void solve(int testNumber, InputReader in, PrintWriter out) { int n = in.nextInt(), k = in.nextInt(); long[] x = new long[n]; for (int i = 0; i < n; i++) { long t = in.nextLong(); x[i] = t; } long ans = LINF; for (int i = 0; i < n && i+k-1 < n; i++) { long tmp = 0; if (x[i+k-1] < 0) { tmp = abs(x[i]); } else if (x[i] < 0 && x[i+k-1] >= 0) { long min = min(abs(x[i]), abs(x[i+k-1])); long max = max(abs(x[i]), abs(x[i+k-1])); tmp = min*2 + max; } else if (x[i] >= 0) { tmp = x[i+k-1]; } ans = min(ans, tmp); } out.println(ans); }
ポイント
- 何を全探索するか
- 方針をちゃんと思考すること
類題
D - Static Sushi
⇒こちらのほうが難しいです。
雑記
これ本番中とけなかったの、なんでか未だによくわからない。多少実装面倒だけど、やるだけ問題・・・。