• [Usaco2008 Nov]Buying Hay 购买干草


    题目描述

    约翰的干草库存已经告罄,他打算为奶牛们采购H(1≤H≤50000)磅干草,他知道N(1≤N≤100)个干草公司,现在用1到N给它们编号。第i个公司卖的干草包重量为Pi(1≤Pi≤5000)磅,需要的开销为Ci(l≤Ci≤5000)美元.每个干草公司的货源都十分充足,可以卖出无限多的干草包.帮助约翰找到最小的开销来满足需要,即采购到至少H磅干草.

    输入格式

    第1行输入N和H,之后N行每行输入一个Pi和Ci.

    输出格式

    最小的开销.


    与普通的完全背包不同的是,这题装的干草可以超过所需的重量。这里介绍两种常见的做法。

    1.把背包总体积往上扩一段,也就是把背包容量扩大。设此时的容量为m'。然后做完全背包即可。最后枚举m~m'的每一位,取最小代价。由于题中的Pi≤5000,所以让m'等于m+5000即可。

    2.刷表法。设当前已经买了j磅的干草,已经买了i-1种干草,每种干草的重量为ci、价格为vi。那么:

    [dp[j+c[i]]=Min(dp[j+c[i]],dp[j]+v[i]) ]

    如果j+c[i]>m,那么直接计算到dp[m]的头上即可。所以把算式微调一下,改为:

    [dp[Min(j+c[i],m)]=Min(dp[Min(j+c[i]),m],dp[j]+v[i]) ]

    第一种的时间复杂度为O(N(M+Max{ci}));第二种为O(NM)。实际上跑得差不多快。

    第二种的代码:

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define maxn 101
    #define maxm 50001
    using namespace std;
     
    int dp[maxm],c[maxn],v[maxn];
    int n,m;
     
    inline int read(){
        register int x(0),f(1); register char c(getchar());
        while(c<'0'||'9'<c){ if(c=='-') f=-1; c=getchar(); }
        while('0'<=c&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
     
    int main(){
        n=read(),m=read();
        for(register int i=1;i<=n;i++) c[i]=read(),v[i]=read();
     
        memset(dp,0x3f,sizeof dp);
        dp[0]=0;
        for(register int i=1;i<=n;i++){
            for(register int j=0;j<=m;j++){
                dp[min(j+c[i],m)]=min(dp[min(j+c[i],m)],dp[j]+v[i]);
            }
        }
        printf("%d
    ",dp[m]);
        return 0;
    }
    
  • 相关阅读:
    [Javascript] Prototype Pattern
    [Typescript] tsexpecterror
    [React] Compound Pattern
    [React] SWR for data fetching
    [Javascript] Factory pattern vs Class instance
    [Typescript] Only Type import or export
    AcWing 1113. 红与黑
    AcWing 178 第K短路
    AcWing 190.字串变换
    AcWing 165 小猫爬山
  • 原文地址:https://www.cnblogs.com/akura/p/10864467.html
Copyright © 2020-2023  润新知