题目:
给定n种物品和一背包。物品i的重量是wi,其价值为vi,背包的容量为W(假定物品重量与背包容量值均为整数)
,应如何选择装入背包中的物品,使得装入背包中物品的总价值最大?设计一个动态规划算法,求解背包问题。
算法思想:
利用动态规划实现
1、定义子问题:
首先考虑参数的确定,在背包问题中,有关参数有 第i件物品以及加入物品后剩余的weight,在这里我们定义从1到i的取部分物品的最优解为B(i,w)。
2、确认DP方程:
这里就有两种情况
case 1:到第i-1件物品时,背包已经满了,显然价值已经最大,那么此时B(i,w)=B(i-1,w);
case 2:当背包未满的时候,最优解就是加入第i件物品或不加入第i件物品较优的那个,即max{B(i-1,w),vi+B(i,w-wi)}
那么base case就是没有物品时的总价值,即B(0,0)=0;
综合起来得到:
3、子问题的求解次序:
这里我们假设每一件物品的重量都是整数,那么根据动态规划的基本方法,我们建立一个矩阵来求解这个DP方程。自上而下,自左向右经过DP方程的计算将数据填入表格,那么最后一行最后一列就是整个背包的最优价值。
我们先给出伪代码,具体代码实现见下方
我们来看一下这个算法的时间复杂度:
这里可以看出来,这个算法的时间复杂度不仅与n(物品个数)有关,还与背包的最大载重有关,而蛮力法的时间复杂度显然是物品序列的自己个数即O(2^n),假如W >2^n时,动态规划反而低效。
代码来啦:
/*给定n种物品和一背包。物品i的重量是wi,其价值为vi,背包的容量为W(假定物品重量与背包容量值均为整数)
,应如何选择装入背包中的物品,使得装入背包中物品的总价值最大?设计一个动态规划算法,求解背包问题。*/
#include <iostream>
#include <vector>
using namespace std;
void knapsack(int products_count, int capacity, vector<int>&weight, vector<int>&value,vector<vector<int>>&result)
{
for (int i = 1; i <= products_count; i++)
{
for (int w = 1; w <= capacity; w++)
{
if (weight[i] <= w)
{
if (value[i] + result[i - 1][w - weight[i]] > result[i - 1][w])
result[i][w] = value[i] + result[i - 1][w - weight[i]];
else
result[i][w] = result[i - 1][w];
}
else
result[i][w] = result[i - 1][w];
}
}
}
void Print(vector<vector<int>>&result, vector<int>weight, vector<int>&x, int products_count, int capacity)
{
for (int i = products_count; i >= 2; i--)
{
if (result[i][capacity] == result[i - 1][capacity])
x[i] = 0;
else
{
x[i] = 1;
capacity = capacity - weight[i];
}
}
x[1] = result[1][capacity] ? 1 : 0;
}
int main()
{
int products_count, capacity;
vector<int>weight(1, 0);
vector<int>value(1, 0);
//输入商品个数和背包容量
cin >> products_count >> capacity;
//输入商品重量与价格
for (int i = 1; i <= products_count; i++)
{
int temp;
cin >> temp;
weight.push_back(temp);
}
for (int i = 1; i <= products_count; i++)
{
int temp;
cin >> temp;
value.push_back(temp);
}
vector<vector<int>>result(products_count + 1, vector<int>(capacity + 1, 0));//初始化结果矩阵
knapsack(products_count, capacity, weight, value, result);
vector<int>x(6, 0);
Print(result, weight, x, products_count, capacity);
for (int i = 1; i <= products_count; i++)
cout << x[i] << " ";
cout << endl;
cout << result[products_count][capacity] << endl;
system("pause");
return 0;
}