动态规划中的0-1背包问题( 体积,重量,价值 )

目录

题目要求

题目分析

解决疑惑

  1.首先提出我最开始的疑惑

  2.解决我的疑惑

  3.疑惑产生的原因

若有其他疑惑可以发表评论,也可以关注私信我,咱们一起分析解决问题!!!

题目代码


题目要求

给定n种物品和一个背包。物品i的重量是wi,体积是bi,其价值为vi,背包的容量为c,容积为d。问应如何选择装入背包中的物品,使得装入背包中物品的总价值最大? 在选择装入背包的物品时,对每种物品只有两个选择:装入或不装入,且不能重复装入。输入数据的第一行分别为:背包的容量c,背包的容积d,物品的个数n。接下来的n行表示n个物品的重量、体积和价值。输出为最大的总价值。

输入样例:

20   15    3

11   7     9

9    5     10

7    10    5

输出样例

19

题目分析

1.对于动态规划问题老生常谈的一个介绍就是:记住你之前做过的事情;

就是将一个大问题,分为若干小问题,对于小问题采取最优解,并将小问题的最优解放入一个动态更新的数组中(一般我们都定义为dp数组),以便对解决更进一步的问题时直接拿已经储存在数组中的前一步的最优解就可以了;

好处,无论最开始的决策如何,对于之后决策都能构成最优解;

2.回到题目

0-1背包在背包问题中很经典,系列还有完全背包,多重背包等,在一些刷题平台上的一些相关题目都是在经典题型上加以修改,装饰

0-1背包对于所给物品只有两种状体,不装,不存在其他状态

题目中给出了三种属性,重量,体积和价值;(比经典题型多了一个体积属性

我们前面说了,动态规划是动态存储每个小问题的最优解;

所以

(1)我们首先要判断对于一个物品是装还是不装(不装,dp数组在这个状态下需要保存前一步的最优解)

(2)然后装,也有两种状态:

            1.装入当前物品前背包中的价值装入后的总价值(那我们肯定是装入

            2.装入当前物品前背包中的价值装入后的总价值

那肯定是不装入,因为每个小问题都要取最优解,这个时候dp数组中的最优解,肯定要是前一个状态的解

对于装与不装,在代码编程中使用状态转移方程(就是两Max)

dp[i][j][k] = max(dp[i - 1][j][k], dp[i - 1][j - w[i]][k - b[i]] + v[i]);
						

上面的dp[i - 1][j - w[i]][k - b[i]] + v[i]  表示放入i物品后的价值
           dp[i - 1][j][k]                            表示没有放入i物品的价值

  (3)更新dp中的数据,需要三重循环,分别对应的是

           0-i的物品,

           背包的容量,

           背包的容积

       在这三重循环的加持先,可以更新dp数组,使得在不同的条件下,选取的最优解

    

解决疑惑

  1.首先提出我最开始的疑惑

    对于代码中的三重循环更新dp数组,为什么背包容量j++,背包体积k++,每次都加一

    对于物品的装与不装,正常的理解不应该是背包容量、背包体积加上所给的物品i的属性吗

  2.解决我的疑惑

     在我之后的了解,我解决了疑惑

     首先dp数组中装入的是背包(他才是主体)每个阶段的最优解,所以这时候的dp数组是一个三维的立体长方体,

    dp数组中存放的是对于每增加一个单位的重量每增加一个单位的体积,这个时候下的背包问题的最优解

  3.疑惑产生的原因

     先入为主的正常思想,偏离了动态规划的中心,背包才是主体,物体只是外在

若有其他疑惑可以发表评论,也可以关注私信我,咱们一起分析解决问题!!!

题目代码

#include <iostream>
#include <cmath>
using namespace std;
const int TOF = 105;

int dp[TOF][TOF][TOF] = {0};//初始化,三维数组有上限
int w[TOF], b[TOF] ,v[TOF]; //w代表重量,b代表体积,v代表价值


int main()
{
    int i, j, k;
    int n, c, d;//c代表背包容量,d代表背包容积
    
    cin >> c >> d>> n;  
    for (i = 1; i < n + 1; i++)
    {
        cin >> w[i] >> b[i] >> v[i];
    }

	for ( i = 1; i <= n; i++)
			for ( j = c; j >= 0; j--)
				for( k = d; k >= 0;  k--)
				{
					if (j >= w[i]&&k >= b[i])
				    {
			     		dp[i][j][k] = max(dp[i - 1][j][k], dp[i - 1][j - w[i]][k - b[i]] + v[i]);
						//dp[i - 1][j - w[i]][k - b[i]] + v[i]  放入i物品后的价值
						//dp[i - 1][j][k]  没有放入i物品的价值
				    }
				    else
				   {
				 	     dp[i][j][k] = dp[i - 1][j][k];
				   }
				}
				
   
    cout << "背包能放物品的最大价值为:" << dp[n][c][d] << endl;
   
}

欢迎大家评论,关注我不迷路,一起共同进步!!!

欢迎大家评论,关注我不迷路,一起共同进步!!!

欢迎大家评论,关注我不迷路,一起共同进步!!!

猜你喜欢

转载自blog.csdn.net/weixin_59367964/article/details/127966238