午餐题解

午餐题解

贪心+dp

1.贪心:

不妨取任意两人i,j,则:

打饭时间为:

\(\sum_{k=1}^{i-1}a_{k}+a_{i}+b_{i},\)

\(\sum_{k=1}^{i-1}a_{k}+a_{i}+\sum_{k=i+1}^{j-1}a_{k}+a_{j}+b_{j}\)

互换后打饭时间为:

\(\sum_{k=1}^{i-1}a_{k}+a_{j}+b_{j},\)

\(\sum_{k=1}^{i-1}a_{k}+a_{j}+\sum_{k=i+1}^{j-1}a_{k}+a_{i}+b_{i}\)

显然:\(\sum_{k=1}^{i-1}a_{k}+a_{j}+\sum_{k=i+1}^{j-1}a_{k}+a_{i}+b_{i}>\sum_{k=1}^{i-1}a_{k}+a_{i}+b_{i},\)

\(\sum_{k=1}^{i-1}a_{k}+a_{i}+\sum_{k=i+1}^{j-1}a_{k}+a_{j}+b_{j}>\sum_{k=1}^{i-1}a_{k}+a_{j}+b_{j},\)

则:比较

\(max(\sum_{k=1}^{i-1}a_{k}+a_{i}+b_{i},\sum_{k=1}^{i-1}a_{k}+a_{i}+\sum_{k=i+1}^{j-1}a_{k}+a_{j}+b_{j})\)\(max(\sum_{k=1}^{i-1}a_{k}+a_{j}+b_{j},\sum_{k=1}^{i-1}a_{k}+a_{j}+\sum_{k=i+1}^{j-1}a_{k}+a_{i}+b_{i})\)

即为比较:

\(\sum_{k=1}^{i-1}a_{k}+a_{i}+\sum_{k=i+1}^{j-1}a_{k}+a_{j}+b_{j}\)

\(\sum_{k=1}^{i-1}a_{k}+a_{j}+\sum_{k=i+1}^{j-1}a_{k}+a_{i}+b_{i}\)

两者之间只有\(b\)不同,故在越后面,b应越小,

将含\(a,b\)的结构体按\(b\)从大到小排序。

2.dp:

设数组\(f[i][j]\)表示到了第i个人,在第一窗口花了j时间的最小的最长时间:

for(int i=1;i<=n;++i){
        sum+=x[i].a;
        for(int j=0;j<=sum;++j){
            f[i][j]=max(f[i-1][j],sum-j+x[i].b);
            //若第二个人选择二号窗口,一号窗口的最长时间为f[i-1][j],之后第二窗口的最长时间为:sum-j+x[i].b(等到第i个人的时间总和不变)
            if(j>=x[i].a) f[i][j]=min(f[i][j],max(j+x[i].b,f[i-1][j-x[i].a]));
            //选一号窗口,第i个人的花费时间为j+x[i].b,前i-1个人花费的最长时间为f[i-1][j-x[i].a]
        }
}

总代码:

#include<bits/stdc++.h>
using namespace std;
const int N=206;
int n,f[N][N*N+N],sum=0,ans=1e9;
struct xd{int a,b;}x[N];
inline int read(){
   int T=0,F=1; char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-') F=-1; ch=getchar();}
   while(ch>='0'&&ch<='9') T=(T<<3)+(T<<1)+(ch-48),ch=getchar();
   return F*T;
}
bool cmp(xd u,xd v){return u.b>v.b;}
int main(){
    n=read();
    for(int i=1;i<=n;++i) x[i].a=read(),x[i].b=read();
    sort(x+1,x+n+1,cmp),memset(f,0x7f,sizeof(f));
    f[0][0]=0;
    for(int i=1;i<=n;++i){
        sum+=x[i].a;
        for(int j=0;j<=sum;++j){
            f[i][j]=max(f[i-1][j],sum-j+x[i].b);
            if(j>=x[i].a) f[i][j]=min(f[i][j],max(j+x[i].b,f[i-1][j-x[i].a]));
        }
    }
    for(int i=0;i<=sum;++i) ans=min(ans,f[n][i]);
    printf("%d\n",ans);
    return 0;
}  
posted @ 2019-08-08 11:05  lsoi_ljk123  阅读(114)  评论(0编辑  收藏  举报