題目:
題意:
一共有個人,每個人都有兩個信息:打飯時間和喫飯時間
現在有兩個窗口可以打飯,問最短多快能使所有人都喫完飯
分析:
假如我們現在已經確定了兩個窗口分別有哪些人,那麼要想使得總時間最短,我們就應該把喫得慢的人儘可能的往前安排
這樣我們要考慮的就是如何安排這兩個窗口的人,設表示前個人中,在第一個窗口的排隊時間爲,第二個窗口的排隊時間爲時最短耗時
但這樣明顯是要的,所以我們必須要省掉一維空間,我們發現的值在每個的時候都是固定的,這樣的話我們就可以用前綴和維護每個的值,留下一個,而用表示
方程呢,我們就考慮當前的會由什麼轉移過來,一個是前面這些人耗得時間會比第個人的總耗時都要多,這樣我們就直接由轉移;另一個當現在是喫得最慢的了,那沒辦法,總時間就是排隊等待的時間加上第個人喫飯的時間
當然,這只是第個人在一號窗口排隊的情況,還有在二號窗口的也是同理
代碼:
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<cmath>
#include<vector>
#define LL long long
using namespace std;
inline LL read() {
LL d=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
return d*f;
}
struct node{
int a,b;
}x[205];
bool cmp(node a,node b) {return a.b>b.b;}
int sum[205];
int f[205][40005];
int main()
{
int n=read();
for(int i=1;i<=n;i++) x[i].a=read(),x[i].b=read();
sort(x+1,x+1+n,cmp);
for(int i=1;i<=n;i++) sum[i]=sum[i-1]+x[i].a;
for(int i=0;i<=n;i++)
for(int j=0;j<=sum[n];j++)
f[i][j]=99999999;
f[0][0]=0;
for(int i=1;i<=n;i++)
{
for(int j=x[i].a;j<=sum[i];j++) f[i][j]=min(f[i][j],max(f[i-1][j-x[i].a],j+x[i].b));
for(int j=0;j<=sum[i];j++) f[i][j]=min(f[i][j],max(f[i-1][j],sum[i]-j+x[i].b));
}
int ans=2147483647;
for(int i=0;i<=sum[n];i++) ans=min(ans,f[n][i]);
cout<<ans;
return 0;
}