AtCoder Beginner Contest 119
AtCoder Beginner Contest 119のふりかえり
結果はA、Bの二完 (AとBしか解けなかったけど緑にいけた)
C問題
やったこと
どうやるのか全く思いつかなかった。どの材料より短いやつは先にのけとく??
解法
N < 8 なので全探索可能(!)。 たけの扱いは4通り。
長さA の竹の “材料” とする
長さ B の竹の材料とする
長さ C の竹の材料とする
使わない
この4N通りを全部試す。深さ優先探索で探索すれば良い。
N, A,B,C = map(int, input().split()) l = sorted([int(input()) for _ in range(N)])[-1::-1] INF = 1e+10 def dfs(cur, a, b, c): if cur == N: # print("a:{}, b:{}, c:{}".format(a,b,c)) # 材料が何も使われないことを防ぐ為にa=b=c=0の時INFを返す # 30は余分に数えているMP return abs(a - A) + abs(b - B) + abs(c - C) - 30 if min(a, b, c) > 0 else INF # cur本めを使わない場合 ret0 = dfs(cur + 1, a, b, c) # cur本めをAに使う場合 ret1 = dfs(cur + 1, a + l[cur], b, c) + 10 # cur本めをBに使う場合 ret2 = dfs(cur + 1, a, b + l[cur], c) + 10 # cur本めをCに使う場合 ret3 = dfs(cur + 1, a, b, c + l[cur]) + 10 print("cur:{}, a:{},b:{},c:{},ret0:{}, ret1:{}, ret2:{}, ret3:{}".format(cur,a,b,c,ret0,ret1,ret2,ret3)) return min(ret0, ret1, ret2, ret3) print(dfs(0, 0, 0, 0))
D問題
やったこと
一番近い神社・寺をみて、それらからもっとも近い寺・神社までの距離を足す。その2つのうち短い方を先に訪れるという戦略をとったが、TLE。
import numpy as np A,B,Q = map(int, input().split()) s_list = [int(input()) for _ in range(A)] t_list = [int(input()) for _ in range(B)] x_list = [int(input()) for _ in range(Q)] # print("s : ",s_list) # print("t : ",t_list) # print("x : ",x_list) s_nearest_t = [] t_nearest_s = [] for s in s_list: t_dis = [abs(s-t) for t in t_list] s_nearest_t.append(np.min(t_dis)) for t in t_list: s_dis = [abs(s-t) for s in s_list] t_nearest_s.append(np.min(s_dis)) def get_ans(s_list, t_list, x): s_res = [abs(s-x) for s in s_list] t_res = [abs(t-x) for t in t_list] s_nearest = np.min(s_res) t_nearest = np.min(t_res) s_nearest_idx = s_res.index(s_nearest) t_nearest_idx = t_res.index(t_nearest) if s_nearest_t[s_nearest_idx] + s_nearest < t_nearest_s[t_nearest_idx] + t_nearest: ans = s_nearest_t[s_nearest_idx] + s_nearest else: ans = t_nearest_s[t_nearest_idx] + t_nearest return ans for x in x_list: print(get_ans(s_list, t_list, x))
解法
二分探索で挿入位置を探すと早い。pythonでは bisect
という標準ライブラリがある。
bisect_right
で挿入位置の一個右のインデックスを得られる。
import bisect A,B,Q = map(int, input().split()) INF = 1e+18 s_list = [-INF] + [int(input()) for _ in range(A)] + [INF] t_list = [-INF] + [int(input()) for _ in range(B)] + [INF] x_list = [int(input()) for _ in range(Q)] def get_ans(s_list, t_list, x): b, d = bisect.bisect_right(s_list, x), bisect.bisect_right(t_list, x) ans = INF for S in [s[b - 1], s[b]]: for T in [t[d - 1], t[d]]: d1, d2 = abs(S - x) + abs(T - S), abs(T - x) + abs(S - T) ans = min(ans, d1, d2) return ans for x in x_list: print(get_ans(s_list, t_list, x))