luogu2577/bzoj1899 午餐 (贪心+dp)
首先,应该尽量让吃饭慢的排在前面,先按这个排个序
然后再来决定每个人到底去哪边
设f[i][j]是做到了第i个人,然后1号窗口目前的总排队时间是j,目前的最大总时间
有这个i和j的话,再预处理出前i个人的排队总时间sum[i],可以知道在2号窗口的排队时间是sum[i]-j
拿着两个去更新答案就行了
1 #include<bits/stdc++.h> 2 #define pa pair<int,int> 3 #define CLR(a,x) memset(a,x,sizeof(a)) 4 using namespace std; 5 typedef long long ll; 6 const int maxn=210; 7 8 inline ll rd(){ 9 ll x=0;char c=getchar();int neg=1; 10 while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();} 11 while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); 12 return x*neg; 13 } 14 15 int f[maxn][maxn*maxn],st[maxn]; 16 int N; 17 struct Node{ 18 int e,q; 19 }p[maxn]; 20 21 inline bool cmp(Node a,Node b){return a.e>b.e;} 22 23 int main(){ 24 //freopen("","r",stdin); 25 int i,j,k; 26 N=rd(); 27 for(i=1;i<=N;i++){ 28 p[i].q=rd(),p[i].e=rd(); 29 }sort(p+1,p+N+1,cmp); 30 for(i=1;i<=N;i++) 31 st[i]=st[i-1]+p[i].q; 32 33 CLR(f,127);f[0][0]=0; 34 for(i=1;i<=N;i++){ 35 for(j=0;j<=N*200;j++){ 36 if(f[i-1][j]>=1e8) continue; 37 f[i][j+p[i].q]=min(f[i][j+p[i].q],max(f[i-1][j],j+p[i].q+p[i].e)); 38 f[i][j]=min(f[i][j],max(f[i-1][j],st[i]-j+p[i].e)); 39 } 40 } 41 int ans=1e9; 42 for(j=0;j<=N*200;j++) 43 ans=min(ans,f[N][j]); 44 printf("%d\n",ans); 45 return 0; 46 }