• 题解 P2517 【[HAOI2010]订货】


    DP做法

    这道题的做法很多,但是我认为~其他题解讲的不很具体~

    我就来讲一下我思考的过程吧qwq

    方程还是比较好列的:设(F[i,j])表示前i个月的任务完成后仓库里剩余的货物量为(j)时的最小花费

    则有方程:

    [F[i,j]=min{F[i-1,k]+m*k+d[i]*(j+u[i]-k)},kleqslant j+u[i] ]

    其中(m*k)为囤积货物的费用,(j+u[i]-k)为这个月新买的货物

    但是这样是(O(n*S^2))的,需要优化:

    把与k有关的项提出来,方程化为:

    [F[i,j]=min{F[i-1,k]+(m-d[i])*k}+d[i]*(j+u[i]),kleqslant min(j+u[i],s) ]

    我们可以先不管与k无关的项,最后再加上即可,先记为:

    [F[i,j]=min{F[i-1,k]+(m-d[i])*k},kleqslant min(j+u[i],s) ]

    再写出(F[i,j-1])的表达式:

    [F[i,j-1]=min{F[i-1,k]+(m-d[i])*k},kleqslant min(j+u[i]-1,s) ]

    便可以发现,(j)每增大(1)(F[i,j])的取值范围只比(F[i,j-1])的取值范围大了(1),那么我们可以将方程化简为:

    [F[i,j]=min(F[i,j-1],F[i,j+u[i]]+(j+u[i])*m-d[i]*(u[i]+j)) ]

    显然 (j=0)的时候需要枚举(k)算一下

    (PS:)注意判断一下(j+u[i])有没有超出边界

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <vector>
    #include <cctype>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    using namespace std;
    
    #define inf 0x3f3f3f3f
    typedef long long LL;
    #define il inline
    
    il int read(int x=0,int f=1,char ch='0')
    {
        while(!isdigit(ch=getchar())) if(ch=='-') f=-1;
        while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
        return f*x;
    }
    
    //f[i][j] :前i个月剩余的货物量为j时的最小花费
    //f[i][j]=min{f[i-1][k]+m*k+d[i]*(j+u[i]-k)},k<=j+u[i]
    
    //f[i][j]=min{f[i-1][k]+(m-d[i])*k},k<=min(j+u[i],s)
    //f[i][j-1]=min{f[i-1][k]+(m-d[i])*k},k<=min(j+u[i]-1,s)
    
    //f[i][j]=min(f[i][j-1],f[i-1][j+u[i]]+(j+u[i])*m-d[i]*(u[i]+j))
    
    //f[i][j]+=+d[i]*(u[i]+j)
    
    const int N=50+5,S=1e4+5;
    int f[N][S];
    int n,m,s;
    int u[N],d[N];
    
    il void work()
    {
        memset(f,0x3f,sizeof(f));
        f[0][0]=0;
        for(int i=1;i<=n;++i)
        {
            for(int k=0;k<=0+u[i]&&k<=s;++k) f[i][0]=min(f[i][0],f[i-1][k]+(m-d[i])*k);
            for(int j=1;j<=s;++j)
            {
                if(j+u[i]<=s) f[i][j]=min(f[i][j-1],f[i-1][j+u[i]]+(j+u[i])*m-d[i]*(u[i]+j));
                else f[i][j]=f[i][j-1];
            }
            for(int j=0;j<=s;++j) f[i][j]+=d[i]*(u[i]+j);
        }
        int ans=f[n][0];
    
        printf("%d
    ",ans);
    }
    
    int main()
    {
        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]);
        work();    
        return 0;
    }
    
  • 相关阅读:
    cocos2d多语言互调之一---lua调java
    vue 组件
    封装 XMLHttpRequest
    Ajax 请求
    jq 显示和隐藏 计时器
    jq 动画DOM及其操作
    jq 表单提交
    jq 事件绑定
    js 一些实用的封装和兼容
    工厂、原型、混合模式
  • 原文地址:https://www.cnblogs.com/wmq12138/p/11210138.html
Copyright © 2020-2023  润新知