[ZJOI2005]午餐 [ZJOI2005]午餐

luogu
BZOJ
一个很符合常理的贪心,吃得久的先打饭,
于是sort一遍
然后f[i][j]表示前i个人,A窗口打饭用了j分钟,吃完饭的最小时间
枚举第i个人在哪个窗口打饭转移

#define ri register int
#include<bits/stdc++.h>
using namespace std;
const int _=205;
inline int re(){
	ri x=0,w=1;register char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
	while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
	return x*w;
}
int n,ans=1e9,s,f[_][_*_];
struct node{int a,b;}p[_];
inline bool cmp(node x,node y){return x.b>y.b;}
int main(){
	n=re();
	for(ri i=1;i<=n;i++)
		p[i].a=re(),p[i].b=re();
	sort(p+1,p+n+1,cmp);
	memset(f,63,sizeof(f));
	f[0][0]=0;
	for(ri i=1;i<=n;i++){
		s+=p[i].a;
		for(ri j=0;j<=s;j++){
			f[i][j]=min(f[i][j],max(f[i-1][j],s-j+p[i].b));
			if(j>=p[i].a)f[i][j]=min(f[i][j],max(f[i-1][j-p[i].a],j+p[i].b));
			if(i==n)ans=min(ans,f[n][j]);
		}
	}
	printf("%d
",ans);
	return 0;
}