• HDU


    题意:01背包:有N件物品和一个容量为V的背包。每种物品均只有一件。第i件物品的费用是volume[i],价值是value[i],求解将哪些物品装入背包可使价值总和最大。

    分析:

    1、构造二维数组:

    dp[i][j]---前i件物品放入一个容量为j的背包可以获得的最大价值。

    dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - volume[i]] + value[i]);---(a)

    (1)dp[i - 1][j]---不放第i件物品,因此前i件物品放入一个容量为j的背包的价值与前i-1件物品放入一个容量为j的背包的价值相同。

    (2)dp[i - 1][j - volume[i]] + value[i]---放入第i件物品,因为当前背包容量为j,所以需要将前i-1件物品放入容量为j-volume[i]的背包里,剩下的容量为volume[i]的空间放第i件物品。

    2、构造滚动数组:(一维)

    dp[j]---当前状态是容量为j的背包所得价值。

    dp[j] = max(dp[j], dp[j - volume[i]] + value[i]);---(b)

    比较上述a式,

    b式中的第一个dp[j]是考虑第i件物品的,即当前状态。

    而 dp[j - volume[i]] + value[i]和第二个dp[j]是考虑第i-1件物品的,即前一个状态。

    因此通过逆序枚举(V……volume[i])的方式更新dp[j]。

    原因:因为如果正序,对于正在考虑的物品i,前面已更新的dp[j]会对后面更大容量的dp[j]的更新产生影响,

    即此时你计算的dp[i][j](用二维数组表示)其实是max(dp[i - 1][j], dp[i][j-volume[i])。

    而逆序枚举,对于当前研究的物品i状态下的dp[j](即将计算),dp[j]和更小容量的dp[j - volume[i]]都是未更新的,也就是我们需要的前一状态,即第i-1件物品的情况。

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cctype>
    #include<cmath>
    #include<iostream>
    #include<sstream>
    #include<iterator>
    #include<algorithm>
    #include<string>
    #include<vector>
    #include<set>
    #include<map>
    #include<stack>
    #include<deque>
    #include<queue>
    #include<list>
    #define lowbit(x) (x & (-x))
    const double eps = 1e-8;
    inline int dcmp(double a, double b){
        if(fabs(a - b) < eps) return 0;
        return a > b ? 1 : -1;
    }
    typedef long long LL;
    typedef unsigned long long ULL;
    const int INT_INF = 0x3f3f3f3f;
    const int INT_M_INF = 0x7f7f7f7f;
    const LL LL_INF = 0x3f3f3f3f3f3f3f3f;
    const LL LL_M_INF = 0x7f7f7f7f7f7f7f7f;
    const int dr[] = {0, 0, -1, 1, -1, -1, 1, 1};
    const int dc[] = {-1, 1, 0, 0, -1, 1, -1, 1};
    const int MOD = 1e9 + 7;
    const double pi = acos(-1.0);
    const int MAXN = 1000 + 10;
    const int MAXT = 10000 + 10;
    using namespace std;
    int value[MAXN], volume[MAXN], dp[MAXN];
    int main(){
        int T;
        scanf("%d", &T);
        while(T--){
            int N, V;
            scanf("%d%d", &N, &V);
            for(int i = 0; i < N; ++i){
                scanf("%d", &value[i]);
            }
            for(int i = 0; i < N; ++i){
                scanf("%d", &volume[i]);
            }
            memset(dp, 0, sizeof dp);
            for(int i = 0; i < N; ++i){
                for(int j = V; j >= volume[i]; --j){
                    dp[j] = max(dp[j], dp[j - volume[i]] + value[i]);
                }
            }
            printf("%d
    ", dp[V]);
        }
        return 0;
    }
    

      

  • 相关阅读:
    WPF 关于拖拽打开文件的注意事项
    asp.net core 3.1中对Mongodb BsonDocument的序列化和反序列化支持
    用百度webuploader分片上传大文件
    多线程学习笔记
    web.config数据库连接字符串加密
    Visual Studio 2010 常用快捷方式
    Team Foundation Server 2013 日常使用使用手册(四)分支与合并
    Team Foundation Server 2013 日常使用使用手册(三)上传新工程、创建任务、创建bug、设置预警
    Team Foundation Server 2013 日常使用使用手册(二)修改、签入、撤销、回滚、对比代码变更
    Team Foundation Server 2013 日常使用使用手册(一)-本地连接TFS、查看任务
  • 原文地址:https://www.cnblogs.com/tyty-Somnuspoppy/p/6919268.html
Copyright © 2020-2023  润新知