[BZOJ1899]Lunch 午餐(DP)
Posted void_f
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ1899]Lunch 午餐(DP)相关的知识,希望对你有一定的参考价值。
首先有个很贪心的思路,吃饭时间长的最先打饭为最优,所以开始先排个序
然后考虑DP,我们不需要知道某个人在哪个对,只要关注总的时间就行了
肯定需要一维表示当前同学编号,还需要表示某个窗口的打饭时间,如果知道其中一个窗口,另一个也可以知道,所以一维就行
那么用f[i][j]表示前i个同学,第一个窗口打饭总时间为j时的答案
s[i]表示排序后前打饭时间前缀和,a表示打饭时间,b表示吃饭时间
- 当前同学放二号窗口,f[i][j]=min{f[i][j],max(f[i-1][j],sum[i-1]-j+A[i].a+A[i].b)}
- 放1号窗口,f[i][j]=min{f[i][j],max(f[i-1][j-A[i].a],j+A[i].b)}
Code
#include <cstdio> #include <algorithm> #include <cstring> #define N 210 using namespace std; struct info{ int a,b; friend bool operator <(info a,info b){ return a.b>b.b; } }A[N]; int n,Ans,s[N],f[N][N*N],sum; inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} return x*f; } int main(){ n=read(); for(int i=1;i<=n;++i) A[i].a=read(),A[i].b=read(); sort(A+1,A+n+1); for(int i=1;i<=n;++i) s[i]=s[i-1]+A[i].a; memset(f,0x3f,sizeof(f));f[0][0]=0; for(int i=1;i<=n;++i) for(int j=0;j<=s[i];++j){ f[i][j]=min(f[i][j],max(f[i-1][j],s[i-1]-j+A[i].a+A[i].b)); if(j>=A[i].a) f[i][j]=min(f[i][j],max(f[i-1][j-A[i].a],j+A[i].b)); } Ans=1e9; for(int i=0;i<=s[n];++i) Ans=min(Ans,f[n][i]); printf("%d\n",Ans); return 0; }
以上是关于[BZOJ1899]Lunch 午餐(DP)的主要内容,如果未能解决你的问题,请参考以下文章