zoukankan      html  css  js  c++  java
  • Luogu P2577 [ZJOI2005]午餐

    一道贪心+类背包DP的好题

    首先发现一个十分显然的性质,没有这个性质整道题目都难以下手:

    无论两队的顺序如何,总是让吃饭慢的人先排队

    这是一个很显然的贪心,因为如果让吃饭慢的排在后面要更多的时间至少没有这样优

    因此我们先按吃饭时间从大到小sort一下

    然后我们发现这是一个类01背包的DP,只不过这里的状态要么是01,要么是10(即要么在1队,要么在2队)

    然后这种东西都有一些很神奇的性质,比如说我们用前缀和sum[i]表示前i个人中排队的总时间,那么

    sum[i]-前i个人中去1号窗口的人的打饭时间之和=前i个人中去1号窗口的人的打饭时间之和

    然后我们可以想出一个DP,用f[i][j]表示前i个人中,在1号窗口排队的人共花了j分钟排队的最优情况下,最少要多少时间(要和2号窗口的取一个min),包括吃饭的时间

    然后就有转移:

    • f[i][j]=min(f[i][j],max(f[i-1][j-a[i].t],j+a[i].e))(在1号窗口打饭)

    • f[i][j]=min(f[i][j],max(f[i-1][j],sum[i]-j+a[i].e)(在2号窗口打饭)

    然后我们发现这个可以滚动存储不过也没这个必要,但是我还是写了

    CODE

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=205;
    struct data
    {
        int t,e;
    }a[N];
    int n,f[2][N*N],sum[N],ans;
    inline char tc(void)
    {
        static char fl[100000],*A=fl,*B=fl;
        return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
    }
    inline void read(int &x)
    {
        x=0; char ch=tc();
        while (ch<'0'||ch>'9') ch=tc();
        while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc();
    }
    inline bool comp(data a,data b)
    {
        return a.e>b.e;
    }
    inline int min(int a,int b)
    {
        return a<b?a:b;
    }
    inline int max(int a,int b)
    {
        return a>b?a:b;
    }
    int main()
    {
        //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
        register int i,j;
        for (read(n),i=1;i<=n;++i)
        read(a[i].t),read(a[i].e);
        sort(a+1,a+n+1,comp);
        for (i=1;i<=n;++i)
        sum[i]=sum[i-1]+a[i].t;
        memset(f[0],63,sizeof(f[0])); f[0][0]=0;
        for (i=1;i<=n;++i)
        {
            int now=i&1,last=now^1;
            memset(f[now],63,sizeof(f[now])); ans=f[now][0];
            for (j=sum[i];j>=0;--j)
            {
                if (j>=a[i].t) f[now][j]=min(f[now][j],max(f[last][j-a[i].t],j+a[i].e));
                if (sum[i]-j>=a[i].t) f[now][j]=min(f[now][j],max(f[last][j],sum[i]-j+a[i].e));
            }
        }
        for (i=0;i<=sum[n];++i)
        ans=min(ans,f[n&1][i]);
        printf("%d",ans);
    }
    
  • 相关阅读:
    axios的数据请求方式及跨域
    vuex 的介绍
    返回顶部的过渡式写法
    数据结构和算法——二叉树
    RecyclerView的刷新和加载更多
    希尔排序小结
    选择排序小结
    插入排序小结
    冒泡、快速排序小结
    数据结构和算法——递归算法
  • 原文地址:https://www.cnblogs.com/cjjsb/p/9016515.html
Copyright © 2011-2022 走看看