zoukankan      html  css  js  c++  java
  • BZOJ2424: [HAOI2010]订货

    【传送门:BZOJ2424


    简要题意:

      给出n天所需要的货物和每一天的货物的单价,可以多买一些货物存放在容量为s的仓库里,每一个货物存放一天需要m的花费,求出满足n天所需的货物的最小花费


    题解:

      先写了个DP方程:f[i][j]=min(f[i][j],f[i-1][k]+d[i]*(j+u[i]-k)+m*k);(0<=j<=s,0<=k<=j+u[i])

      O(n*s^2),T的结果很明显

      优化一下,很容易发现其实f数组是具有一定的单调性的

      那么用单调队列来优化一下下

      当f[i-1][list[head]]+d[i]*(j+u[i]-list[head])+m*list[head]>f[i-1][list[head+1]]+d[i]*(j+u[i]-list[head+1])+m*list[head+1]的时候说明list[head+1]对于当前情况更优,所以head++,不过要判断一下list[head+1]是否<=j+u[i]

      其实f[i-1][list[head]]+d[i]*(j+u[i]-list[head])+m*list[head]>f[i-1][list[head+1]]+d[i]*(j+u[i]-list[head+1])+m*list[head+1]

      可以转化为f[i-1][list[head]]-(d[i]-m)*list[head]>f[i-1][list[head+1]]-(d[i]-m)*list[head+1],将其中不变的值去掉


    参考代码:

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    int u[51],d[51];
    int f[51][11000];
    int list[11000];
    int main()
    {
        int n,m,s;
        scanf("%d%d%d",&n,&m,&s);
        for(int i=1;i<=n;i++) scanf("%d",&u[i]);
        for(int i=1;i<=n;i++) scanf("%d",&d[i]);
        memset(f,63,sizeof(f));
        f[0][0]=0;
        for(int i=1;i<=n;i++)
        {
            int head=1,tail=s+1;
            for(int j=0;j<=s;j++) list[j+1]=j;
            for(int j=0;j<=s;j++)
            {
                while(head<=tail&&f[i-1][list[head]]-(d[i]-m)*list[head]>f[i-1][list[head+1]]-(d[i]-m)*list[head+1]&&list[head+1]<=j+u[i]) head++;
                int k=list[head];
                f[i][j]=f[i-1][k]+d[i]*(j+u[i]-k)+m*k;
            }
        }
        printf("%d
    ",f[n][0]);
        return 0;
    }

     

  • 相关阅读:
    url
    松弛时间
    Linux下为当前用户添加 PYTHONPATH 环境变量
    ElasticSearch集群的安装(windows)
    软件开发安全
    java,判断手机设备跟adb建立连接
    question
    氚云后台代码小栗子,流程表单新增完成反写源单状态
    November Challenge 2020 Division 1
    February Challenge 2021 Division 1 选做
  • 原文地址:https://www.cnblogs.com/Never-mind/p/8458922.html
Copyright © 2011-2022 走看看