动态规化——01背包问题

题目描述:

现有一个能装下20kg的背包,和 [ 重量 , 价值 ]的珠宝分别为[2,3] [3,4] [4,5] [5,8] [7,10]的珠宝各一件,分别设为1-5号珠宝。

如何获得最大价值?

 

解题:

 重量价值
123
234
345
458
5910

 

设B(k,w)为,w为剩余的背包容量,k为前k个商品。

则B(k,w)的含义为,当背包容量为w时,偷前4个商品能获得的最大容量。

 

那么可以分为以下三种情况:

  1. 第k件珠宝已经装不下,那么B(k,w) = B(k-1,w)
  2. 第k件珠宝装得下,并偷走,那么B(k,w) = B(k-1,w-w_k) + v_k
  3. 第k件珠宝装得下,但是不偷,那么B(k,w) = B(k-1,w)   (就是和第一种情况是一样的)

 

整个过程大概是就是如下图所示(懒的画那么多)

 

 

 

那么整个问题就可以对两种情况分别递归,最后比较两个递归得到的值

 

代码:

#include<iostream>
#include<algorithm>
using namespace std;

class Knapsack{
    private:
        int vs[6] = {0,3,4,5,8,10};     //价值
        int ws[6] = {0,2,3,4,5,9};      //重量
    public:
        void Solution(int n){
            int res = ks(5,n);      //递归
            cout<<res<<endl;
        }

        int ks(int k,int w){
            int res = 0;
            if( k==0 || w==0 )
                return 0;
            else if(ws[k]>w)
                res = ks(k-1,w);                        //重量不够
            else{                                       //重量够
                int temp1 = ks(k-1,w-ws[k])+vs[k];      //偷
                int temp2 = ks(k-1,w);                  //不偷
                res = max(temp1,temp2);
            }
            return res;
        }
};

int main(){
    Knapsack test;
    test.Solution(20);
    return 0;
}

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值