bzoj1899

显然如果只有一个窗口,是一道贪心的题目,直接让吃饭慢的排在前面即可

两个窗口的话,我们还是根据这个原则

先对吃饭时间降序排序,然后这是一个dp

假如设当前处理到第i个人,当在窗口1的打饭时间确定了,窗口2的打饭时间也就知道了

我们用f[i,j]表示到第i个人,窗口1的打饭时间为j时的最快集合时间

然后dp搞一下就行了

 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.
View Code
原文地址:https://www.cnblogs.com/phile/p/4473162.html