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 }

 

posted @ 2018-10-22 22:27  Ressed  阅读(136)  评论(0编辑  收藏  举报