背包问题(01背包)

--------开始--------

         每次用到背包问题就忘,今天特意把背包问题写下来,本篇只写01背包问题,至于其它的背包问题以后会陆续出现,大多数背包问题都是以01背包为原型来演变过来的,所以先介绍经典的01背包问题。

         01背包问题是动态规划的典型例题,0  1顾名思义就是一个物品有两种情况,拿或者不拿,每种物品有且仅有一件,用子问题定义状态:即f[i][j]表示前i件物品恰放入一个容量为j的背包可以获得的最大价值。则其状态转移方程便是:

                                                                                                                 

f[i][j]=max( f[i-1][j],f[i-1][j-v[i]]+w[i] )

      至于这个方程怎么推导出来的,我后面会介绍,总之,这个状态转移方程特别重要,其它背包问题的状态转移方程也都是又它衍生出来的,可以说它的作用非常重要。

      我们先来看下01背包的题目 :

问题

有 N 件物品和一个容量是 的背包。每件物品只能使用一次。

第 件物品的体积是 v,价值是 wi 

求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。

输入格式

第一行两个整数,NV,用空格隔开,分别表示物品数量和背包容积。

接下来有 N 行,每行两个整数 vi wi ,用空格隔开,分别表示第 i 件物品的体积和价值。

输出格式

输出一个整数,表示最大价值。

数据范围

0<N,V10000<N,V≤1000
0<vi,wi1000

输入样例

4 5
1 2
2 4
3 4
4 5

输出样例:

8

 问题特点很明确:每件物品只有一件我们可以选择拿或者不拿,我们定义v[ i ]为物品的体积,w[i]为物品的价值。

我们再来看状态转移方程  f[ i ][ j ] = max ( f[ i-1 ][ j ] , f[ i-1 ][ j-v[ i ] ] + w[ i ] )

f[i][j]就是前i件物品,在体积为j的情况下最大价值是多少。

我们要计算在有限空间中怎么才能价值最大,可以通过转化求在n件物品和n-1件物品(放第n件物品或者不放)中求最大价值,所以我们需要求n-1件物品时的最大价值,进而类似递归需要求n-1件物品和n-2件物品中的最大值,一直到最后一件,从第一件推回第n件就是我们的结果。

1. 选第i件物品 f[i][j] = f[i - 1][j - v[i]] ;

2. 不选第i件物品 f[i][j] = f[i - 1][j] ;

然后我们的答案就是res = max{ f[n][0V] } ;

 

     

for(int i = 1;i <= n;i++)
      for(int j = 0;j <= m;j++)
      {
        f[i][j] = f[i-1][j];
          if(j >= v[i])
              f[i][j] = max(f[i-1][j-v[i]]+w[i],f[i][j]); }
      int res=0;
      for(int i =0;i <= m;i++)
        res = max(res,f[n][i]);

以上描述的方法的时间和空间复杂度均为O(VN),但是时间复杂度应该已经不能再优化了,而空间复杂度却可以优化到O(V),即可以把二维数组变成一维数组,至于如何优化会在下次再继续讲解。

PS : 题目来源: https://www.acwing.com/problem/content/2/
参考文章: https://blog.csdn.net/u013445530/article/details/40210587

--------结束--------

原文地址:https://www.cnblogs.com/chuyds/p/10531006.html