问题描述:
n个物品组成集合O,每个商品有两个属性vi(所占体积)和pi(价格)
背包容量为C
输出商品子集S属于O,使价格最大,体积不超过背包体积
递推公式:(先上后下)
#include<iostream>
using namespace std;
int v[] = { 0 , 10 , 3 , 4 , 5 , 4 }; //商品的体积10 , 3 , 4 , 5 , 4
int p[] = { 0 , 24 , 2 , 9 , 10 , 9 }; //商品的价值24 , 2 , 9 , 10 , 9
const int m = 5; //商品数目
const int C = 13; //背包大小
int dp[m+1][C+1] = { { 0 } }; //动态规划表 dp[i][j] i表示物品序号,j表示背包所剩空间
int Rec[m+1][C+1]= { { 0 } }; //动态规划表,用于存储是否选择该商品
int item[m+1]; //最优解情况,0为未选择,1为选择
void KnapsackDP() { //动态规划
for (int i = 0; i <= m; i++)
Rec[i][0] = dp[i][0] = 0;
for (int i = 0; i <= C; i++)
Rec[0][i] = dp[0][i] = 0;
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= C; j++) {
if (j >= v[i] && dp[i - 1][j] < dp[i - 1][j - v[i]] + p[i]){
dp[i][j] = dp[i - 1][j - v[i]] + p[i];
//构造dp数组,包中装入第i个商品
Rec[i][j] = 1; //选则了第i个
}
else {
dp[i][j] = dp[i - 1][j];//最优解向下瞬移
Rec[i][j] = 0; //第i个未被选择
//if (j >= v[i]) {
// if (dp[i - 1][j] < dp[i - 1][j - v[i]] + p[i]){
// dp[i][j] = dp[i - 1][j - v[i]] + p[i];
// //构造dp数组,包中装入第i个商品
// Rec[i][j] = 1; //选则了第i个
// }
// else {
// dp[i][j] = dp[i - 1][j];
// Rec[i][j] = 0; //第i个未被选择
// }
//}
//else {
// dp[i][j] = dp[i - 1][j];
// Rec[i][j] = 0;
}
}
}
}
void IsSelect(int i, int j) { //解析最优解
if (i > 0) {
if (Rec[i][j]>0) {
item[i] = 1;
}
else
item[i] = 0;
IsSelect(i - 1, j - v[i]);
}
}
void Print() {
for (int i = 0; i <= m; i++) { //输出dp数组
for (int j = 0; j <= C; j++) {
cout << dp[i][j] << "\t";
}
cout << endl;
}
cout << endl;
for (int i = 0; i <= m; i++) { //输出Rec数组
for (int j = 0; j <= C; j++) {
cout << Rec[i][j] << "\t";
}
cout << endl;
}
cout << endl;
for (int i = 1; i <= m; i++)
cout << item[i] << " ";
cout << endl;
}
int main()
{
KnapsackDP();
IsSelect(m, C);
Print();
return 0;
}
运行结果: