0/1背包问题与最大收益

   

      池塘的水满了,雨也停了,田边的稀泥里到处是泥鳅。

      不过,今天不捉泥鳅,而是去捉螃蟹,待会儿太阳小点就出发。拿个袋子,当然是捉得越多越好,于是想到类似的经典问题:

      小偷夜入宝地,可偷宝贝甚多,然背包承重有限,最大收益几何?

     这是一个典型的0/1背包问题,为什么叫0/1背包问题呢?因为对于一件宝贝,小偷要么选择偷它,要么选择不偷它。小偷陷入了左右为难的境地,我们对小偷的困难进行分析和具体化。

     假设小偷进入宝地,发现了4件宝贝,其价值V分别是2元、3元、4元、5元,对应的重量W分别是1斤、2斤、3斤、4斤,小偷的背包最大承重是7斤,那么小偷的最大收益是多少元呢?

i1234
V2元3元4元5元
W1斤2斤3斤4斤

       

      显然,可用动态规划来思考,并找出递推关系式。我们来定义状态:在承重为j的限制下,记f[i][j]是前i件宝贝能达到的最大收益。那么,F[4][7]即为小偷的目标。现在的问题是:要求出f[i][j]的递推关系式。 

      我们考察第i件宝贝,只有两种情况:小偷要么选择它,要么不选择它。然后在这两种情况中求较大值,便形成了递推关系式。直接看程序,递推关系式便体现在其中:

#include<iostream>
using namespace std;  
 
#define N 4 // 总共N件宝贝
#define V 7 // V是背包的承重极限值
 
int main()  
{  
  int value[N + 1]  = {0, 2, 3, 4, 5}; // 宝贝的价值
  int weight[N + 1] = {0, 1, 2, 3, 4}; // 宝贝的重量
  int f[N + 1][V + 1] = {0}; // f[i][j]表示在背包承重为j的情况下,前i件宝贝的最大价值
 
  int i = 1;
  int j = 1;
  for(i = 1; i <= N; i++)
  {
    for(j = 1; j <= V; j++)
    {
      // 递推关系式
      if(j < weight[i])
      {
        f[i][j] = f[i - 1][j];
      }
      else
      {
        int x = f[i - 1][j]; // case1: 不选择第i件宝贝
        int y = f[i - 1][j - weight[i]] + value[i]; // case2: 选择第i件宝贝
        f[i][j] = x < y ? y : x;
      }
    }
  }
 
  cout << f[N][V] << endl; // 10

  return 0;  
}

     程序的结果是10元, 这就是小偷的最大收益。

       

     在之前的文章中,我们聊过动态规划:动态规划的本质。熟练掌握动态规划,才能获得最大收益,能捉到的螃蟹也会更多。

      走,捉螃蟹去。

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值