0-1背包问题
0-1背包问题是一个典型的动态规划问题。
描述如下:现在又一个可以载重量为M的背包,另外有N个物品,每个物品重量和价值分别为w[i]和v[i],现在要求选择物品放入背包,使其在不超过重量的情况下有最大价值。
问题的递推表达式如下:设C为当前背包的容量。
当w[n] > C时, f(n, C) = f(n-1, C)
当w[n] <=C时, f(n, C) = max{f(n-1, C), v[n] + f(n-1, C-w[n])}
可以利用上式得到采用递归方法计算函数f的代码,递归结束是:f(i, 0) = 0或 f(0, j)=0.
另外也可以根据上面的最优子结构采用动态规划的方法,使用work[N+1][M+1]数组,其中work[i][j] 表示前i个物品放入载重量为j的背包中时能得到的最大价值。
以数据
10,3 //分别表示M和N
3,4 //表示每个物品的重量和价值
4,5
5,6
为例,得到的work矩阵如下:
第一行,第一列一定均为0,j为1和2时,因为w[i] < j, 所以取 f(n-1, j),所以也都为0, 在以后的更新中,进行递推式比较,注意是将 f(n-1, j)和f(n-1, j-w[i])相比,所以只要当前物品重量w[i]小于背包总量j时即可进行是否加入的判断。代码如下:
1 //0-1背包问题 2 3 #include<iostream> 4 #include<fstream> 5 #include<vector> 6 using namespace std; 7 8 class Bag{ 9 public: 10 Bag(){} 11 12 void parse(ifstream & fin); 13 14 void getMaxValue(); 15 16 private: 17 int number; 18 int weight; 19 vector<int> w; 20 vector<int> v; //分别表示每个物品的重量和价值。 21 22 }; 23 24 void Bag::parse(ifstream & fin) 25 { 26 fin >> weight >> number; 27 28 int tempv, tempw; 29 w.push_back(0); 30 v.push_back(0); 31 for(int i = 0; i < number; i++) 32 { 33 fin >> tempw >> tempv; 34 w.push_back(tempw); 35 v.push_back(tempv); 36 } 37 } 38 39 void Bag::getMaxValue() 40 { 41 vector<int> t(weight+1, 0); 42 vector<vector<int> > work(number+1,t); //初始化number*weight的全0数组, 行表示前i个物品,被装入载重量为j的背包 43 44 for(int i = 1; i <= number; i++) 45 for(int j = 1; j <= weight; j++) 46 { 47 if(w[i] <= j) //注意,不要忘记等于的情况!! 48 { 49 int temp = work[i-1][j-w[i]] + v[i]; 50 if(temp > work[i-1][j]) 51 work[i][j] = temp; 52 else 53 work[i][j] = work[i-1][j]; 54 }else 55 work[i][j] = work[i-1][j]; 56 } 57 /////////////////结果输出 58 for(int i = 0; i <= number; i++) 59 { 60 for(int j = 0; j <= weight; j++) 61 { 62 cout << work[i][j]<< " "; 63 } 64 cout << endl; 65 } 66 cout << "the max value is " << work[number][weight] << endl; 67 ///////////////////////////// 68 } 69 70 int main() 71 { 72 ifstream fin("in.txt"); 73 Bag b; 74 b.parse(fin); 75 b.getMaxValue(); 76 77 system("pause"); 78 return 0; 79 }