一、实验目的: 理解并掌握利用-动态规划算法与贪心算法求解不同背包问题。 | |||||||||
给定n种物品和一个背包。物品i的重量是w[i],其价值为vi,背包的容量为C。问如何选择装入背包的物品,使得装入背包中物品的总价值最大? 在选择装入背包的物品时,对每种物品i只有两种选择,即装入背包或不装入背包。不能将物品装入背包多次,也不能只装入部分的物品,因此称之为0-1背包问题。 2. 小数背包问题 给定n种物品和一个背包。物品i的重量是w[i],其价值为vi,背包的容量为C。问如何选择装入背包的物品,使得装入背包中物品的总价值最大? 在选择物品i装入背包时,可以选择物品i的一部分,而不一定要全部装入背包。 程序代码:
#include <iostream> #include <string> using namespace std; const int N = 150;//定义全局变量使N值不变 int max(int a, int b); int v[N]; //价值数组 int w[N]; //重量数组 int n, c; //n个数,c容量 int i, j; int recursion() { int V[N][N]; //建立一个二维数组,v(i,j)中i表示考虑第i到第n个物品,j表示当前容量 for (i = 0; i <= n; i++) V[i][0] = 0; for (j = 0; j <= c; j++) V[0][j] = 0; //计算第i行,进行第i次迭代 for (i = 1; i <= n; i++) { for (j = 1; j <= c; j++) { if (j < w[i])//此时背包剩余容量小于第i个物品所以不装第i个物品,便成立考虑 第i-1到第n个物品 V[i][j] = V[i - 1][j]; else V[i][j] = max(V[i - 1][j], V[i - 1][j - w[i]] + v[i]); //V[i - 1][j]表示没有装第i个物品, V[i - 1][j - w[i]] + v[i] 表示装了第i个物品再考虑考虑第i-1到第n个物品 } } j = c; cout << "装入的物品:"; for (i = n; i > 0; i--) { if (V[i][j] > V[i - 1][j])//前者价值大于后者说明装了第i个物品 { cout << "\n"; cout << "装入第" << i << "个物品"; j = j - w[i]; continue; } else cout << "\n"; cout << "不装入第" << i << "个物品"; } return V[n][c]; } int max(int a, int b) { if (a >= b) return a; else return b; } int input() { cout << "请输入物品的个数: "; cin >> n; cout << "请输入背包的容量: "; cin >> c; for (i = 1; i <= n; i++) { cout << "请输入第" << i << "个物品的质量: "; cin >> w[i]; } for (j = 1; j <= n; j++) { cout << "输入第" << j << "个物品的价值: "; cin >> v[j]; } } int main() { input(); cout << "最大价值为:" << recursion() << endl; return 0; }
#include <iostream> #include <string> using namespace std; const int N = 150; int max(float p[N], int n) { float max = p[0]; int maxi = 0; for (int i = 0; i < n; i++) { if (p[i] > max) { max = p[i]; maxi = i; } } p[maxi] = 0; return maxi; } void traceback(int n, int c, int w[N], int v[N]) { float p[N];//价值权重 int i; int weight = 0;float value = 0;//总重量,总价值 for (i = 0; i < n; i++) //权重计算 p[i] = v[i] / (w[i]*1.0); for (i = 0; i < n; i++) { int num = max(p, n);//价值最高的下标 weight += w[num]; if (weight < c) { cout << "装入物品" << i+1 << "的重量为 " << w[num] << " 价值为 " << v[num] << " 完整装入" << endl; value += v[num]; } else if (weight > c) { float w1 = (c - (weight- w[num])) /( w[num]*1.0);//计算装入部分 cout << "装入物品" << i+1 << "的重量为 " << w[num] << " 价值为 " << v[num] << " 装入百分之" << w1*100 << endl; weight = c; value += w1 * v[num]; } else break; } cout << "装入的总重量为 " << weight << endl; cout << "装入的总价值为 " << value << endl; } int main() { int v[N]; int w[N]; int n, c; cout << "请输入物品的个数: "; cin >> n; cout << "请输入背包的容量: "; cin >> c; int i, j; for (i = 0; i < n; i++) { cout << "请输入第" << i + 1 << "个物品的质量: "; cin >> w[i]; } for (j = 0; j < n; j++) { cout << "输入第" << j + 1 << "个物品的价值: "; cin >> v[j]; } traceback(n, c, w, v); return 0; } 程序测试及运行结果: 01:
小数: 分析与讨论:
设是所给0-1背包问题的一个最优解,则是下面相应子问题的一个最优解 设子问题的最优值为其中是背包容量为,可选择物品为时0-1背包问题的最优值,就可以得到递推公式。 小数背包问题运用贪心算法 其算法与0-1背包大体相似,贪心算法解决小数背包问题与0-1背包的整数规划问题最大的不同小数背包问题需要算出每个物品的权重,通过比较权重大小,来判断放入背包的顺序,直到背包放满。 |