显然如果只有一个窗口,是一道贪心的题目,直接让吃饭慢的排在前面即可
两个窗口的话,我们还是根据这个原则
先对吃饭时间降序排序,然后这是一个dp
假如设当前处理到第i个人,当在窗口1的打饭时间确定了,窗口2的打饭时间也就知道了
我们用f[i,j]表示到第i个人,窗口1的打饭时间为j时的最快集合时间
然后dp搞一下就行了
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 const inf=1000000007; 2 var a,b,s:array[0..500] of longint; 3 f:array[0..200,0..40010] of longint; 4 n,i,j,ans:longint; 5 function max(a,b:longint):longint; 6 begin 7 if a>b then exit(a) else exit(b); 8 end; 9 10 function min(a,b:longint):longint; 11 begin 12 if a>b then exit(b) else exit(a); 13 end; 14 15 procedure swap(var a,b:longint); 16 var c:longint; 17 begin 18 c:=a; 19 a:=b; 20 b:=c; 21 end; 22 23 procedure sort(l,r: longint); 24 var i,j,x,y: longint; 25 begin 26 i:=l; 27 j:=r; 28 x:=a[(l+r) div 2]; 29 repeat 30 while a[i]>x do inc(i); 31 while x>a[j] do dec(j); 32 if not(i>j) then 33 begin 34 swap(a[i],a[j]); 35 swap(b[i],b[j]); 36 inc(i); 37 j:=j-1; 38 end; 39 until i>j; 40 if l<j then sort(l,j); 41 if i<r then sort(i,r); 42 end; 43 44 begin 45 readln(n); 46 for i:=1 to n do 47 readln(b[i],a[i]); 48 sort(1,n); 49 for i:=1 to n do 50 s[i]:=s[i-1]+b[i]; 51 for i:=0 to n do 52 for j:=0 to s[n] do 53 f[i,j]:=inf; 54 f[0,0]:=0; 55 for i:=1 to n do 56 for j:=0 to s[i-1] do 57 begin 58 f[i,j]:=min(f[i,j],max(f[i-1,j],s[i]-j+a[i])); //排在窗口2 59 f[i,j+b[i]]:=min(f[i,j+b[i]],max(j+b[i]+a[i],f[i-1,j])); //排在窗口1 60 end; 61 62 ans:=inf; 63 for i:=0 to s[n] do 64 ans:=min(ans,f[n,i]); 65 writeln(ans); 66 end.