算法:动态规划之背包问题

背包问题,动态规划经典问题,几个不同价值和权重的物品,一个给定满权重的背包,求装满背包权重所能获得的最大价值。


01背包问题

题目:一个绿茶有很多的舔狗,她为了维持女神形象,对微信的最大回复流量为4(超过就会CPU过载,发消息串流,被发现是海王),现在舔狗1号小王(想你的夜)发送消息的流量是1,绿茶能从其获得的价值是15,舔狗2号小李(pc被抓)发送消息的流量是3,绿茶能从其获得的价值是20,舔狗3号小吴(我大你忍)发送消息的流量是4,绿茶能从其获得的价值是30,现在你的女神为了养鱼不被发现,请你帮忙计算一下,怎么能在不串流的情况下选择合适的舔狗获得最大的价值。

首先考虑暴力的解法

最朴素的解法,暴力枚举。由排列组合计算所有的可能性

只选一个人

1号 流量 1 价值15 y

2号 流量 3 价值20 y

3号 流量 4 价值30 y

选两个人

1和2 流量 4 价值 35 y

1和3 流量 5 价值 45 n

2和4 流量 7 价值 50 n

三个人 

1,2,3 流量8 价值 65 n

显然,由枚举能获得的最大流量为35,其余的超过绿茶能把握的最大流量。

优化 从占据流量最大的人开始

仅仅有3号时 流量是4 ,最大价值为 30 流量为4时的最大价值更新为30

当2号加入     流量是4 ,流量是3号的4 价值是3号的30 ,

                                       要么流量是2号的3 价值是2号的20

                                       能把握的最大为价值为30 ,流量为4

当1号加入,查询4号,此时,4号此时的最大流量为30,遍历到2号时,发现二号距离最大的流量还有1个流量,所以去查流量为1时所能获得的价值,此时流量1的价值为15,故15+20>30,流量为4时更新。

故代码中,dp数组,其下标含义为,此时流量为i时,所能获得的最大价值。

代码

#include <climits>  
#include <iostream>  
#include <vector>  
  
using namespace std;  
  
// 计算在给定权重限制下能获得的最大物品价值  
void max_value_with_weight_limit()  
{  
    vector<vector<int>> v_list = {{1, 15}, {3, 20}, {4, 30}};  
    int power = 4;  
    vector<int> f1(power + 1, 0);   
    for (auto& rtn : v_list)  
    {  
        //从后向前更新
        for (int j = power; j >= rtn[0]; --j) // 从power递减到rtn[0]  
        {  
            f1[j] = max(f1[j], f1[j-rtn[0]] + rtn[1]); // 更新价值  
        }  
    }  
    cout << f1[power] << "\n"; // 输出最大价值  
}  
  
int main()  
{  
    max_value_with_weight_limit();  
    return 0;  
}

留下的问题,思考:为什么要从后往前更新?从前向后更新呢?

todo!

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值