背包问题基础-01背包

在看这篇文章之前,最好要有一定的DP基础:

题目链接:http://acm.nefu.edu.cn/JudgeOnline/problemShow.php?problem_id=1712 

简单来说就是你有一个承重量为m的背包,然后给你n个物品的重量和价值,求背包中能装物品的最大价值。

此类问题,有一套固定的模板,如题解报告中所给出的。接下来,我将此题的题解报告为例,分析问题思路。

1. 首先推出状态转移方程:dp[j]=max(dp[j],dp[j-w[i]]+v[i])

先看题目所给的数据:背包容量为10,共有4个物品,4个物品的重量和价值分别为(2,1),(3,3),(4,5),(7,9)。

首先,在背包容量给定的情况下,对于每一种物品,都有放与不放入背包两种选择。若将物品放入背包,则背包容量减少,价值增加,不放入背包,价值和容量不变。

设背包容量m,w[i]表示第i件物品重量,v[i]表示第i件物品价值,dp[j]表示经过i轮物品选择之后背包容量为j时背包中物品最大价值。

现在,我们假设有一张表(如下图),这张表上给出了对于每一种背包容量和经过i轮物品选择后,背包所能具有的最大价值(那么表格的最后一行最后一列即为答案)。如图中的红色位置就表示背包容量为5,经过(2,1),(3,3),(4,5)三件物品选择后,背包所能具有的最大价值。假设红色位置的值未知,即dp[5]的值未知,那么现在我们要做的就是选择要不要将(4,5)这件物品放入背包。如果不放入,我们可以把背包容量留给下一次物品选择的时候用,此时经过三轮选择后的最大价值还是经过前两轮选择后的dp[5]。如果放入,那么背包容量就减少为5-4=1,就相当与在放入第三件物品之前,背包容量就只有1,或者说只能提供1,因为其余的4个背包容量要留给本轮选择,那么此时背包内物品最大价值就等于经过两轮选择后的dp[1]+5,而经过两轮选择后的dp[1]的值我们已知。由此,易得dp[5]=max(dp[5], dp[5-4]+5) ,因此对于表中任意一种状态我们都有dp[j]=max(dp[j],dp[j-w[i]]+v[i]),要明白等式右边的dp[j]值与dp[j-w[i]]的值是上一轮的。

2. 接下来我们要做的,就是根据上面的思想,把那张表用程序打出来,最后的dp[10]就是答案,看题解报告。

#include <bits/stdc++.h>

using namespace std;
int w[500],c[500],dp[500];
int v,n;
int main()
{
   cin>>v>>n;             //输入背包容量和物品数量
   for(int i=1;i<=n;i++)
   cin>>w[i]>>c[i];       //将物品重量和价值存入数组
    
   //memset(dp,0,sizeof(dp);

   for(int i=1;i<=n;i++)
   for(int j=v;j>=w[i];j--)
   dp[j]=max(dp[j],dp[j-w[i]]+c[i]);


    cout <<dp[v] << endl;
    return 0;
}

首先对于这道题,只需要一个一维数组dp[ ]即可,因为我们进行max()判断的时候只用到上一次选择的结果。

中间我空出来的部分就是打表过程。第一个for循环是进行n次物品选择,在看第二个for循环之前要说明一个问题,就是其实在打表之前应该将数组dp[ ]初始化为0,但因为c++默认把未赋值的数组初始化为0,所以省略,所以要明白在进行第一次选择时,上一次的dp[ ]值是都为0的。我们来看第二个for循环,第二个for循环就是逐个打出背包容量从m一直到1的值。要明白几点:第二个for循环应该从最大值背包容量开始,因为获取dp[x]的值时只会用到dp[x]之前的值。而如果先从小的值开始,那么得到的结果会覆盖上一次选择的结果。其次j应该在<w[i]之前结束,因为,j<w[i]意味着此时背包容量已经装不下当前判断的物品,所以没必要再判断,直接继承上一次的结果即可,若进行了判断,则会出现dp[负数]这样的情况。

3. OK,至此,所有内容讲完。可能这与大家在网上看到的其它教程所用方法有些不一样,因为他们采用的是自顶向上推理状态转移方程的方法,用的是二位数组,后续的话可能会向大家介绍这种方法。另外,由于我把所有我自己理解过程中所遇到问题和大家可能遇到的问题都列举了出来,所以我觉得我讲的有些啰嗦了,如果大家还有什么不懂的,欢迎留言啊。

发布了34 篇原创文章 · 获赞 26 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/sinat_40471574/article/details/89740300