Problem:


Twin book report

-->

双子の読書感想文

双子のアミとマミが通う学校では早くも夏休みに突入し，今年もおびただしい量の宿題が出された．
しかし，遊び盛りの2人は今日も宿題には一切手をつけずに外へ遊びに行こうとしていた．
このままでは夏休み最終日に泣きを見るのは明らかなので，保護者役のあなたは，心を鬼にして今日は読書感想文の宿題が終わるまで2人を家から出さないことにした．

準備の良いあなたは既に図書館から全ての課題図書を借りてある．
ただし，図書館の規則により各本は1冊ずつしか借りられていない．
さて，教育上の理由から2人には互いに協力することなく，それぞれ全ての本を読み，感想を書いてもらう事にした．
加えて，本の返却期限が近いため，まずはなるべく早くすべての本を読み終えるようにしてもらう事にした．
そして，あなたはその条件下でなるべく早く宿題が終わるような宿題の進め方を考えることにした．
ここで，本を読み終えた時間，宿題を終えた時間は，それぞれ双子の両方が作業を終えた時間で考える．

各本は1冊ずつしかないため，2人が同時刻に同じ本を読むことはできない．
加えて，大人の事情により，ある本を読み始めたらそれを中断する事はできず，ある本についての感想文を書き始めたらそれを中断することもできない．
当然ながら，読んでいない本について感想を書くこともできない．
なお，アミとマミは双子であるため，各本について読むのにかかる時間，感想文を書くのにかかる時間は2人で共通している．

例えば，3冊の本があり，それぞれ本を読むのにかかる時間，感想文を書くのにかかる時間が以下の通りであるとする．

      
    
    本を読む時間
    感想文を書く時間

    本1
    5
    3

    本2
    1
    2

    本3
    1
    2

この場合は，図C-1のように宿題を進めると，時間10で全ての本を読み終え，時間15で宿題を終える事ができる．
図C-2の進め方では時間14で宿題を終えているが，本を読み終える時間が最短でないため，今回は採用できない．
また，図C-3のように2人が同時に同じ本を読んだり， 図C-4のように本を読むのを中断したり，読んでいない本の感想を書く事もできない．

図 C-1: 最短で宿題を終わらせる進め方の例

図 C-2: 本を読み終える時間が最短でない例

図 C-3: 2人が同時に同じ本を読んでしまっている例

図 C-4: 読んでいない本の感想を書いたり，作業を中断したりしている例

様々な大人の事情を考慮しつつ，遊びに行きたがっている双子のためになるべく早く宿題が終わるような進め方を考えてあげよう．

Input

入力は複数のデータセットから構成される．各データセットの形式は次の通りである．

N
r1 w1
r2 w2
...
rN wN

Nは課題図書の数を表す整数であり，1以上1,000以下と仮定して良い．

続くN行は課題図書についての情報を表す．
各行はスペースで区切られた2つの整数を含み，ri (1 &#8804; ri &#8804; 1,000) は i 番目の本を読むのにかかる時間，wi (1 &#8804; wi &#8804; 1,000) は i 番目の本の感想文を書くのにかかる時間を表す．

N=0 は入力の終わりを示す．
これはデータセットには含めない．

Output

各データセットについて，2人が全ての本を読み終えるまでの時間を最小にしたときの，全ての感想文を書き終えるまでの最小の時間を1行に出力しなさい．

Sample Input

4
1 1
3 1
4 1
2 1
3
5 3
1 2
1 2
1
1000 1000
10
5 62
10 68
15 72
20 73
25 75
30 77
35 79
40 82
45 100
815 283
6
74 78
53 55
77 77
12 13
39 42
1 1
0

Output for Sample Input

14
15
3000
2013
522



Sample input:
4
1 1
3 1
4 1
2 1
3
5 3
1 2
1 2
1
1000 1000
10
5 62
10 68
15 72
20 73
25 75
30 77
35 79
40 82
45 100
815 283
6
74 78
53 55
77 77
12 13
39 42
1 1
0


Sample output:
14
15
3000
2013
522

Submission status: Accepted

Solution code:
while True:
    n=int(input())
    if n==0:
        break
    books=[]
    read_t=0
    write_t=0
    for i in range(n):
        r,w=map(int,input().split())
        read_t+=r
        write_t+=w
        books.append((r,w))
    books=sorted(books)
    if books[-1][0]<=read_t//2:
        print(read_t+write_t)
        continue
    sukima=books[-1][0]-(read_t-books[-1][0])
    dp=[[0 for i in range(sukima+1)] for i in range(n)]
    for i in range(1,n):
        for j in range(1,sukima+1):
            dp[i][j]=max(dp[i-1][j],
            dp[i-1][j-books[i-1][1]]
            +books[i-1][1] if j-books[i-1][1]>=0 else 0)

    print(read_t+write_t+sukima-dp[-1][-1])

Submission status: Accepted

Solution code:
import sys
sys.setrecursionlimit(10000000)
input=lambda : sys.stdin.readline().rstrip()

while True:
    n=int(input())
    if n==0:
        break
    books=[]
    read_t=0
    write_t=0
    for i in range(n):
        r,w=map(int,input().split())
        read_t+=r
        write_t+=w
        books.append((r,w))
    books=sorted(books)
    if books[-1][0]<=read_t//2:
        print(read_t+write_t)
        continue
    sukima=books[-1][0]-(read_t-books[-1][0])
    dp=[[0 for i in range(sukima+1)] for i in range(n)]
    for i in range(1,n):
        for j in range(1,sukima+1):
            dp[i][j]=max(dp[i-1][j],
            dp[i-1][j-books[i-1][1]]
            +books[i-1][1] if j-books[i-1][1]>=0 else 0)

    print(read_t+write_t+sukima-dp[-1][-1])

Submission status: Accepted

Solution code:
while True:
    N = input()
    if N == 0:
        break
    data = [map(int,raw_input().split()) for _ in xrange(N)]
    data.sort(key = lambda x:-x[0])
    R,W = zip(*data)
    empty = max(0,R[0]-sum(R[1:]))
    #print "empty",empty
    dp = [False]*(empty+1)
    dp[0] = True
    ma = 0
    for w in W[-1:0:-1]:
        if empty < w:
            break
        for i in xrange(empty,-1,-1):
            if dp[i] and i+w <= empty:
                ma = max(ma, i+w)
                dp[i+w] = True
    #print filter(lambda x: dp[x], xrange(empty+1))
    print sum(R)+sum(W)+(empty-ma)

Submission status: Accepted

Solution code:
#coding:utf-8
from __future__ import division,print_function
try:
    input = raw_input
except NameError:
    pass

from datetime import datetime
import math

MAXW = 1001

def solve(n, read, write):
    sumR = sum(read)
    sumW = sum(write)

    next = []
    base = -1
    for i in range(n):
        if read[i] < sumR // 2:
            next.append((read[i], write[i]))
        else:
            base = read[i]
    if (len(next) == n):
        print(sumR + sumW)
        return

    dp = [False] * MAXW
    dp[0] = True
    for i in range(n - 1):
        tmp = dp[:]
        for j in range(base + 1):
            if dp[j]:
                na = j + next[i][0]
                nb = j + next[i][0] + next[i][1]
                if na <= base:
                    tmp[na] = True
                if nb <= base:
                    tmp[nb] = True
        dp = tmp
    res = 0
    for i in range(base + 1):
        if dp[i]:
            res = base - i
    print(sumR + sumW + res)

def main():
    while True:
        n = int(input())
        if n == 0: return
        read = []
        write = []
        for i in range(n):
            r, w = map(int, input().split())
            read.append(r)
            write.append(w)
        solve(n, read, write)

main()

Submission status: Accepted

Solution code:
import operator
import sys
def solve():
    readline = sys.stdin.readline
    write = sys.stdout.write
    N = int(readline())
    if N == 0:
        return False
    P = [list(map(int, readline().split())) for i in range(N)]
    P.sort(key = operator.itemgetter(0))
    RS = sum(r for r, w in P)
    WS = sum(w for r, w in P)
    if all(2*r <= RS for r, w in P):
        write("%d\n" % (RS + WS))
        return True
    rl, sl = P[-1]

    W = 2*rl - RS
    dp = [0]*(W+1)
    dp[0] = 1
    for r, w in P[:-1]:
        for j in range(W, w-1, -1):
            dp[j] |= dp[j-w]
    ma = max(j for j in range(W+1) if dp[j])
    write("%d\n" % (RS + WS + (W - ma)))
    return True
while solve():
    ...

Submission status: Accepted

Solution code:
import math,string,itertools,fractions,heapq,collections,re,array,bisect,sys,random,time,copy,functools

sys.setrecursionlimit(10**7)
inf = 10**20
eps = 1.0 / 10**13
mod = 10**9+7
dd = [(-1,0),(0,1),(1,0),(0,-1)]
ddn = [(-1,0),(-1,1),(0,1),(1,1),(1,0),(1,-1),(0,-1),(-1,-1)]

def LI(): return [int(x) for x in sys.stdin.readline().split()]
def LI_(): return [int(x)-1 for x in sys.stdin.readline().split()]
def LF(): return [float(x) for x in sys.stdin.readline().split()]
def LS(): return sys.stdin.readline().split()
def I(): return int(sys.stdin.readline())
def F(): return float(sys.stdin.readline())
def S(): return input()
def pf(s): return print(s, flush=True)


def main():
    rr = []

    def f(n):
        a = [LI() for _ in range(n)]
        t = max(map(lambda x: x[0]*2+x[1], a))
        u = sum(map(sum,a))
        mx = max(map(lambda x: [x[0],-x[1]], a))
        mxi = a.index([mx[0], -mx[1]])
        k = sum(map(lambda x: x[0], a)) - mx[0]
        if k < mx[0]:
            mx0 = mx[0]
            dp = [0] * (mx0+1)
            dp[k] = 1
            for ai in range(n):
                if ai == mxi:
                    continue
                c = a[ai][1]
                for i in range(mx0-c,-1,-1):
                    dp[i+c] |= dp[i]
            mt = 0
            for i in range(mx0,-1,-1):
                if dp[i]:
                    mt = i
                    break
            u += (mx0 - mt)
        return max(t,u)

    while 1:
        n = I()
        if n == 0:
            break
        rr.append(f(n))
        # print('rr', rr[-1])

    return '\n'.join(map(str,rr))


print(main())