def read_data(): N = int(input()) VT = [] for n in range(N): v, t = map(int, input().split()) VT.append((v + t, v, t)) return N, VT def solve(N, VT): VT.sort(reverse=True) upper = min(VT[0][0], sum(v for vt, v, t in VT) + 1) lower = 1 while lower + 1 < upper: mid = (upper + lower) // 2 if is_valid(mid, VT): lower = mid else: upper = mid return lower def is_valid(val, VT): used = [False] * len(VT) lower = val upper = float('inf') return dfs(lower, upper, VT, used) def dfs(lower, upper, VT, used): '''VTのうち、used でないものを使って、lower 以上、upper 未満の選び方をできるかを返す。 ''' for i, (val, v, t) in enumerate(VT): if val < lower: return False if used[i] or v >= upper: continue if v >= lower: return True used[i] = True result = dfs(lower - v, min(upper, t), VT, used) used[i] = False if result: return True return False N, VT = read_data() print(solve(N, VT))