
显然如果只有一个窗口,是一道贪心的题目,直接让吃饭慢的排在前面即可
两个窗口的话,我们还是根据这个原则
先对吃饭时间降序排序,然后这是一个dp
假如设当前处理到第i个人,当在窗口1的打饭时间确定了,窗口2的打饭时间也就知道了
我们用f[i,j]表示到第i个人,窗口1的打饭时间为j时的最快集合时间
然后dp搞一下就行了
const inf=;
var a,b,s:array[..] of longint;
f:array[..,..] of longint;
n,i,j,ans:longint;
function max(a,b:longint):longint;
begin
if a>b then exit(a) else exit(b);
end; function min(a,b:longint):longint;
begin
if a>b then exit(b) else exit(a);
end; procedure swap(var a,b:longint);
var c:longint;
begin
c:=a;
a:=b;
b:=c;
end; procedure sort(l,r: longint);
var i,j,x,y: longint;
begin
i:=l;
j:=r;
x:=a[(l+r) div ];
repeat
while a[i]>x do inc(i);
while x>a[j] do dec(j);
if not(i>j) then
begin
swap(a[i],a[j]);
swap(b[i],b[j]);
inc(i);
j:=j-;
end;
until i>j;
if l<j then sort(l,j);
if i<r then sort(i,r);
end; begin
readln(n);
for i:= to n do
readln(b[i],a[i]);
sort(,n);
for i:= to n do
s[i]:=s[i-]+b[i];
for i:= to n do
for j:= to s[n] do
f[i,j]:=inf;
f[,]:=;
for i:= to n do
for j:= to s[i-] do
begin
f[i,j]:=min(f[i,j],max(f[i-,j],s[i]-j+a[i])); //排在窗口2
f[i,j+b[i]]:=min(f[i,j+b[i]],max(j+b[i]+a[i],f[i-,j])); //排在窗口1
end; ans:=inf;
for i:= to s[n] do
ans:=min(ans,f[n,i]);
writeln(ans);
end.