01背包问题
背包问题是著名的NP完全问题,在实际生活中有广泛的应用。01背包是背包问题中的一种,也是较简单的一种,利用动态规划的思想可以寻求01背包的解。
问题描述
设有n个物品,他们具有各自的重量w和价值v;给定一个具有一个容量W的背包,求将物品有选择的放入背包中,使得装入的物品的价值之和最大?
01背包:物品是完整个体,只存在放或不放两种状态,不能放入一部分。
分析设计
动态规划求解问题需要找到可分解的大问题,将问题不断划分为子问题就可以求解,通过一个二维数组构成的表的形式记录子问题,最终大问题的解也可以求解出来。
01背包问题中的子问题是什么?
- 更少的物品:当只有0件物品时,答案就很明显了,不用放;
- 更小的背包:当背包的容量为0时,答案就很明显了,放不了。
因此构建二维数组,其中表示:当前背包容量为j,物品有前i个可以放,此时的背包问题的。
只要我们能找到一个递推关系,能使我们从算到即可,就是整个大问题的解。
对于求,当前商品存在了两种可能:
- 新的物品i加进来,背包放不下,即第i件物品在背包容量为k的情况下不放入背包——;
- 新的物品i加进来,背包能放下,但装了也不一定能达到更优的值,还是需要选择第i件物品装与不装——;
最后,就是对表的初始化了,上面已经讨论过了,当没有物品时,当背包容量为0时,即;
运用动态规划的思想解01背包问题的时间复杂度为O(nW)。
源代码
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
//物品类型
struct goods{
int weight; //物品重量
int value; //物品价值
};
//非递归解法
int Knapsack(goods g[],int number,int capacity){
vector<vector<int> > k(number + 1, vector<int>(capacity + 1)); //初始化记录数组
for (int i = 0; i < number; i++)
k[i][0] = 0;
for (int i = 0; i < capacity; i++)
k[0][i] = 0;
for (int i = 1; i <= number; i++) {
for (int j = 1; j <= capacity; j++) {
if (j < g[i - 1].weight)
k[i][j] = k[i - 1][j]; //放不下
else
k[i][j] = max(k[i - 1][j], k[i - 1][j - g[i-1].weight] + g[i-1].value); //放得下,进行比较
}
}
return k[number][capacity];
}
//递归解法
int MFKnapsack(goods g[], int number, int capacity) {
vector<vector<int> > k(number + 1, vector<int>(capacity + 1)); //初始化记录数组
for (int i = 0; i <= number; i++)
for (int j = 0; j <= capacity; j++)
k[i][j] = -1;
for (int i = 0; i < number; i++)
k[i][0] = 0;
for (int i = 0; i < capacity; i++)
k[0][i] = 0;
if (k[number][capacity] < 0) {
int value;
if (capacity < g[number - 1].weight)
value = MFKnapsack(g, number - 1, capacity); //放不下
else
value = max(MFKnapsack(g, number - 1, capacity), MFKnapsack(g, number - 1, capacity - g[number].weight) + g[number].value); //放得下,进行比较
k[number][capacity] = value;
}
return k[number][capacity];
}
int main() {
int capacity, number;
cout << "输入背包容量:";
cin >> capacity;
cout << "输入物品个数:";
cin >> number;
goods *g = new goods[number];
cout << "输入物品信息:(重量w 价值v)" << endl;
for (int i = 0; i < number; i++)
cin >> g[i].weight >> g[i].value;
cout << "背包最大价值为:";
cout<<Knapsack(g,number,capacity)<<endl; //非递归
//cout << MFKnapsack(g, number, capacity) << endl; //递归
delete []g;
system("pause");
return 0;
}
运行结果
来源:https://blog.csdn.net/weixin_42182525/article/details/98960071