• AcWing 8. 二维费用的背包问题


    题目传送门

    问题:二维费用\(01\)背包问题

    题目描述
    \(n\) 件物品 和 一个容量为 \(V\) 的背包,背包最大承重是 \(M\)
    每件物品只能 用一次,第 \(i\) 件物品的 体积\(v_i\)重量\(m_i\),价值 是 \(w_i\)
    求解一个选物品的 方案,使得 总体积 不超过 \(V\)总重量 不超过 \(M\) 的,且 总价值 最大

    分析
    每件物品只能 用一次 因此是个 01背包模型

    费用一共有两个,一个是 体积,一个是 重量,因此是个 01背包二维费用问题

    本题是一道裸题,直接上 闫氏DP分析法

    闫氏DP分析法

    初始状态:f[0][0][0]

    目标状态:f[n][V][M]

    一、三维数组解朴素解法

    #include <bits/stdc++.h>
    
    using namespace std;
    const int N = 1010;
    const int M = 110;
    int n;//n个物品
    int V;//包的体积上限
    int Z;//包的重量上限
    int v1[N];//体积
    int v2[N];//重量
    int w[N];//价值
    int f[N][M][M];//三维的dp数组,描述前i个物品,体积j,重量k时的最大价值
    
    //问题:二维费用的01背包问题[三维数组解法]
    /**
     状态转移方程:
    
     (1)当剩余的空间j不能装下当前物品i,即j<v1[i]时不能选择i物品。
     f[i,j,k]=f[i−1,j−vi,k−mi]+wi
    
     (2)当剩余的重量k不能装下当前物品i,即k<v2[i]时不有选择i物品。
     f[i,j,k]=f[i−1,j−vi,k−mi]+wi
    
     (3)当j>=v1[i]&&k>=v2[i]时,可以选择要i,还是不要i。
     f[i,j,k]=max(f[i−1,j,k],f[i−1,j−vi,k−mi]+wi)
     */
    
    /**
    4 5 6
    1 2 3
    2 4 4
    3 4 5
    4 5 6
    
    答案:8
    */
    int main() {
        cin >> n >> V >> Z;
        //体积,重量,价值
        for (int i = 1; i <= n; i++) cin >> v1[i] >> v2[i] >> w[i];
        //遍历每一个物品
        for (int i = 1; i <= n; i++)
            for (int j = 0; j <= V; j++)//体积
                for (int k = 0; k <= Z; k++) //重量
                    //第i个物品不能要
                    if (j < v1[i] || k < v2[i]) f[i][j][k] = f[i - 1][j][k];
                        //第i个物品可以要,还要继续讨论要还是不要
                    else f[i][j][k] = max(f[i - 1][j - v1[i]][k - v2[i]] + w[i], f[i - 1][j][k]);
        //输出
        printf("%d", f[n][V][Z]);
        return 0;
    }
    
    
    

    二、二维数组空间优化解法

    #include <bits/stdc++.h>
    
    using namespace std;
    const int N = 1010;
    const int M = 110;
    int n;//n个物品
    int V;//体积上限
    int Z;//重量上限
    int v1[N];//每个物品的体积
    int v2[N];//每个物品的重量
    int w[N];//每个物品的价值
    int f[M][M];//二维的dp数组,描述前i个物品
    
    signed main() {
        cin >> n >> V >> Z;
        //体积,重量,价值
        for (int i = 1; i <= n; i++) cin >> v1[i] >> v2[i] >> w[i];
        //遍历每一个物品
        for (int i = 1; i <= n; i++)
            for (int j = V; j >= v1[i]; j--)     //由大到小遍历每一个体积
                for (int k = Z; k >= v2[i]; k--) //由大到小遍历每一个重量
                    f[j][k] = max(f[j - v1[i]][k - v2[i]] + w[i], f[j][k]);//动态转移方程,01 背包的思路
        //输出
        printf("%d", f[V][Z]);
        return 0;
    }
    
    
    
  • 相关阅读:
    用于验证码图片识别的类(C#源码)
    一起学习Windows Phone7开发(十八. Windows Phone7 Toolkit)
    Microsoft Enterprise Library 5.0 系列(五) Data Access Application Block
    用C#生成随机中文汉字验证码的基本原理
    win7中安装vs2008的升级成正式版的方法
    sqlserver 常用存储过程集锦
    Windows Phone 7 Developer Tools & Training Kit 正式版发布!
    c# 图片存储方式
    C# winform 上传文件 (多种方案)
    一致性Hash算法(KetamaHash)的c#实现
  • 原文地址:https://www.cnblogs.com/littlehb/p/15684961.html
Copyright © 2020-2023  润新知