算法笔记(c++)--完全背包问题

          算法笔记(c++)--完全背包和多重背包问题


完全背包

完全背包不同于01背包-完全背包里面的东西数量无限

假设现在有5种物品重量为5,4,3,2,1

          价值为1,2,3,4,5

        背包容量为10

#include <iostream>
#include<algorithm>

using namespace std;
int main() 
{
    int total_weight = 10;
    int w[6] = { 0,5,4,3,2,1};
    int v[6] = { 0,1,2,3,4,5};
    int dp[11] = { 0 };
    for (int i = 1; i <= 5; i++)
        for (int j = w[i]; j <= 10;j++)
                dp[j] = max(dp[j],dp[j - w[i]] + v[i]);
    cout << "总的价值为: " << dp[10] << endl;
    return 0;
}

其他都和01背包一样,就是遍历j时候的初始化不一样。

这里的dp[j]还是表示前i件物品放入一个为j容量的背包获得的最大价值,每次更新必然保证是当前最优解。就像求最长递增子序列一样。都是把所有情况过一遍然后拿最大的结果。

不多讲直接推算几步就全懂了。

1)首先是当只有物品1号的时候,j初始化为1号物品的重量为5

dp[5]=max(dp[5],dp[5-5]+1]=1

dp[6]到dp[9]都是1,dp[10]=2

2)然后现在是有物品1号和2号,j初始化为2号物品重量4

dp[4]=max(dp[4],dp[4-4]+2)=2

dp[5]=max(dp[5],dp[5-4]+2)=2

dp[..8]=max(dp[8],dp[8-4]+2)=4

 其实到这里也差不多了,下面都是一样的。

我们要决定是不是要放这个物品,就从这个物品的大小出发遍历背包容量,然后每次遍历都对比下假如现在腾出这个物品的空间并且放进去比原来的价值还大的话,就放进去。

区别------------01背包和完全背包

01背包遍历是反向的,这样更新就不会影响前面的。

而完全背包正向遍历,会改变前面的所以也就可出现多次存放的了。






多重背包

多重背包再加点限制,数量有限制。

数据如下:

数量重量价值
000
151
242
133
224
115

同样设背包为10大小

代码如下:

#include <iostream>
#include<algorithm>
using namespace std;
int main()
{
    int total_weight = 10;
    int w[6] = { 0,5,4,3,2,1 };
    int v[6] = { 0,1,2,3,4,5 };
    int cot[6] = { 0,1,2,1,2,1 };
    int dp[11] = { 0 };
    for (int i = 1; i <= 5; i++)
        for (int k = 1; k <= cot[i];k++)
            for (int j = 10; j >= w[i]; j--)
                dp[j] = max(dp[j], dp[j - w[i]] + v[i]);
    cout << "总的价值为: " << dp[10] << endl;
    return 0;
}

这次不一步步来了,懂01就可以了。

因为每次01都是放一个而完全背包是放多个,我们也不知道完全 背包放了几个。所以多重背包算是01背包的变种。

既然我们每次遍历都是判断放不放这一个物品,那我们干脆就有几个就遍历几遍。再遍历外面再加一个for就好了

很好理解。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
0-1背包问题是一个经典的动态规划问题,但是也可以使用贪心算法来求解。以下是使用贪心算法求解0-1背包问题的思路: 1. 将物品按照单位重量的价值从大到小排序。 2. 依次将物品放入背包中,如果能放下就放入,直到背包装满为止。 以下是使用C++实现贪心算法求解0-1背包问题的代码: ```c++ #include <iostream> #include <algorithm> using namespace std; struct item { int weight; // 物品重量 int value; // 物品价值 double unitValue; // 物品单位重量价值 }; bool cmp(item a, item b) { return a.unitValue > b.unitValue; } int knapsack(item items[], int n, int capacity) { // 将物品按照单位重量价值从大到小排序 sort(items, items+n, cmp); int ans = 0; // 最大价值 // 依次将物品放入背包中 for (int i = 0; i < n; i++) { if (items[i].weight <= capacity) { ans += items[i].value; capacity -= items[i].weight; } else { ans += items[i].unitValue * capacity; break; } } return ans; } int main() { int n = 5; int capacity = 10; item items[n] = {{2, 6}, {2, 3}, {6, 5}, {5, 4}, {4, 6}}; for (int i = 0; i < n; i++) { items[i].unitValue = items[i].value * 1.0 / items[i].weight; } int ans = knapsack(items, n, capacity); cout << "最大价值:" << ans << endl; return 0; } ``` 以上代码的输出结果为: ``` 最大价值:19 ``` 其中,物品的重量和价值分别存储在`item`结构体的`weight`和`value`成员变量中,`unitValue`成员变量表示单位重量的价值。使用`sort()`函数将物品按照单位重量价值从大到小排序,然后依次将物品放入背包中,直到背包装满为止。最后返回背包中物品的总价值即为最大价值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值