问题的提出
背包问题(Knapsack problem)是一种组合优化的NP完全问题。
问题可以描述为:给定一组物品,每种物品都有自己的重量和价格,
在限定的总重量内,我们如何选择,才能使得物品的总价格最高。
问题解决
本文介绍使用动态规划的方法解决此问题
算法思想:
- 1.将原问题分解为子问题:原问题为求解最大价值,分解为背包载重容量从1到最大量c分别能装多少价值东西的 若干问题
- 2.确定状态:使用 sum_value_matrix[n][c]保存,n表示前n个物件(number),c表达背包容量(capacity),所以这个变量意义为背包容量为c,前n个物件能装入的最大价值
- 3.确定初始态值:当容量为1时,因为所有物品重量都大于1,所以sum_value_matrix[n][1]={0,0,0,0,0}
- 4.确定状态转移方程:sum_value_matrix[n][c]=max(sum_value_matrix[n-1][c], sum_value_matrix[n-1][c-w[n]]+v[n])
w[i]表示第i个物件的重量(weight),v[n]表示第一个物件的价值(value)
方程意义:
考虑第n件物品 放1 或者 不放0 时,
如果不放,那么其价值为前面 n-1 物品价值 sum_value_matrix[n-1][c]
如果放,那么其价值为前面 n-1 物品在容量为 c-w[n] 的时候的价值sum_value_matrix[n-1][c-w[n]],
加上第n件物品的价值 v[n](理由:满足“最优化原理”)
代码:
C++代码
class PackageSolver {
public:
int sum_value_matrix[6][11];
int knapsack(PackageItem* items) {
init(items);
for (int c = 2; c <= 10; c++) {
for (int n = 2; n <= 5; n++) {
if (c < items[n].weight) {
//背包capacity 比第n项小
sum_value_matrix[n][c] = sum_value_matrix[n - 1][c];
}
else {
//装得下第n项
//undo: c - items[n].weight>0? else?
int temp1 = sum_value_matrix[n - 1][c];
int temp2 = items[n].value;
if (c - items[n].weight > 0) {
temp2 = sum_value_matrix[n - 1][c - items[n].weight] + items[n].value;
}
sum_value_matrix[n][c] = temp1 > temp2 ? temp1 : temp2;
}
}
}
return sum_value_matrix[5][10];
}
//初始化
void init(PackageItem* items) {
//初始化0
for (int n = 1; n <= 5; n++) {
for (int c = 1; c <= 10; c++) {
sum_value_matrix[n][c] = 0;
}
}
//初始化第一列,第n件物品的weight value
for (int n = 1; n <= 5; n++) {
sum_value_matrix[n][1] = 0;
}
//初始化第一行,只装第一个物品 容量为c时候的 总value
for (int c = 1; c <= 10; c++) {
if (c >= items[1].value) {
sum_value_matrix[1][c] = items[1].value;
}
//cout << sum_value_matrix[1][c];
}
}
void print() {
cout<<"x:capacity y:top n items"<<endl;
for (int n = 1; n <= 5; n++) {
for (int c = 1; c <= 10; c++) {
cout << sum_value_matrix[n][c] << ends;
}
cout << endl;
}
cout << endl;
}
};
背包项
struct PackageItem
{
string name;
int weight;
int value;
PackageItem(string name, int weight, int value) {
this->name = name;
this->weight = weight;
this->value = value;
}
void print() {
cout << "name:" << name << ends
<< "weight:" << weight << ends
<< "value:" << value << endl;
}
};
测试代码
class Problem2Tester {
public:
//为了使得下标与实际意义一致,所以设置item[0]为空
struct PackageItem items[6] = {
{ " ", 0, 0 },
{ "a", 2, 2 },
{ "b", 2, 3 },
{ "c", 6, 5 },
{ "d", 5, 4 },
{ "e", 4, 6 },
};
PackageSolver ps;
void item_test() {
for (int i = 0; i <= 5; i++) {
items[i].print();
}
}
void init_test() {
ps.print();
ps.init(items);
ps.print();
}
void knapsack_test() {
ps.init(items);
ps.print();
ps.knapsack(items);
ps.print();
}
}tester2;
参考:
http://blog.csdn.net/mu399/article/details/7722810
http://blog.sina.com.cn/s/blog_6dcd26b301013810.html