单个背包问题程序与感受(动态规划)
Posted Mem_Ocean
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单个背包问题程序与感受(动态规划)相关的知识,希望对你有一定的参考价值。
样例及程序参考《挑战程序设计竞赛》P349页的例题 DPL_1_B Knapsack Problem
第一行输入2个整数N、W,用空格隔开。接下来N行输入第i个物品的价值vi与重量wi,每个物品占一行,相邻数值之间用空格隔开。
1 /* 2 关于单个背包算法的感悟, 3 该算法的关键实际上就是C[Nmax][Wmax]数组 4 针对单个的C[i][w],其意义就是在前i个货物之中,经过挑选,得到一种“选择方案”, 5 这个“选择方案”的条件就是这两个: 6 1.在前i个货物中选择; 7 2.容量最大为w; 8 3.当前条件下价值value总和最大 9 10 为了实现,该代码选择从最开始的第一个货物出发,先把第一个货物的所有w情况填满, 11 然后再考虑有两个货物(货物一,货物二)的在各个w的情况填满,再加入第三个,第四 12 个……一个一个货物地加,直到所有货物都加进来,并且推算出了“前N个货物,容量为W” 13 的让价值最大的最佳选择方案。 14 在推算的过程中,有两个很重要的推算式子 15 前提******************* items[i].weight<=w *********************************** 16 17 ①C[i][w]=C[i-1][w](C[i-1][w]>=C[i-1][w-items[i].weight]) 18 19 |w| 20 * 21 * 22 * 23 |i-1|******C[i-1][w] 24 | 25 v 26 |i|********C[i][w] 27 28 ②C[i][w]=items[i].value+C[i-1][w-items[i].weight](C[i-1][w]<items[i].value+C[i-1][w-items[i].weight]) 29 30 |w-items[i].weight|*****************|w| 31 * * 32 * * 33 * * 34 |i-1|**C[i-1][w-items[i].weight] * 35 \ * 36 \ * 37 \ * 38 \ * 39 \ * 40 \ * 41 \ * 42 \ * 43 \ * 44 \ * 45 \ * 46 \ * 47 > * 48 |i|************************************items[i].value+C[i-1][w-items[i].weight] 49 50 G[Nmax][Wmax]用于输出“方案”,此处不必多说 51 */ 52 /* 53 输入样例 54 4 5 55 4 2 56 5 2 57 2 1 58 8 3 59 输出样例 60 maxvalue:13 61 0 0 0 0 0 0 62 0 0 4 4 4 4 63 0 0 5 5 9 9 64 0 2 5 7 9 11 65 0 2 5 8 10 13 66 \ \ \ \ \ 67 v v v v v v 68 | | \ \ \ 69 v v v v v v 70 | | \ \ \ 71 v v v v v v 72 | \ | \ | 73 v v v v v v 74 | | | \ \ 75 v v v v v v 76 in 2 77 in 4 78 */ 79 #include<iostream> 80 #include<algorithm> 81 #include<vector> 82 #define Nmax 100+5 83 #define Mmax 10000+5 84 #define diagonal 1 85 #define top 0 86 using namespace std; 87 struct item{ 88 int value,weight; 89 }; 90 int N,W; 91 item items[Nmax+1]; 92 int C[Nmax][Mmax];//以C[i][w]为例子,意思是前i个物品装入容量为w的背包的价值的最大值 93 int G[Nmax][Mmax];//记录选择状态 94 void compute(int &maxvalue,vector<int> &selection){ 95 for(int w=0;w<=W;w++){ 96 C[0][w]=0;//货物0不存在 97 G[0][w]=diagonal;//状态标记 98 } 99 for(int i=1;i<=N;i++) C[i][0]=0; 100 101 for(int i=1;i<=N;i++){ 102 for(int w=1;w<=W;w++){ 103 C[i][w]=C[i-1][w];//假定不选择i货物 104 G[i][w]=top; 105 if(items[i].weight>w) continue;//容量不够,跳过本次选择 106 if(items[i].value+C[i-1][w-items[i].weight]>C[i-1][w]){//选择了i货物,是否更好? 107 C[i][w]=items[i].value+C[i-1][w-items[i].weight];//更好,更新C[i][w] 108 G[i][w]=diagonal; //状态标记 109 } 110 } 111 } 112 maxvalue=C[N][W];//N个货物,W容量的单个背包的分配最佳方案的价值 113 //生成选择路径 114 selection.clear(); 115 for(int i=N,w=W;i>=1;i--){ 116 if(G[i][w]==diagonal){// 117 selection.push_back(i);//载入选择路径vector中 118 w-=items[i].weight;//减去当前货物的容量,此时为C[i-1][w-items[i].weight],也就是到了 119 //“前i-1个货物,容量为w-items[i].weight的最大价值”的情况 120 //依据G[i-1][w-items[i].weight]的状态,来判断该货物有没有选取, 121 //如果是top,则未选取,如果是diagonal,则选取了,载入选择路径vector中 122 } 123 } 124 reverse(selection.begin(),selection.end());//由于是倒着录的,所以要倒转过来。 125 } 126 void input(){ 127 cin>>N>>W; 128 for(int i=1;i<=N;i++){ 129 cin>>items[i].value>>items[i].weight; 130 } 131 } 132 int main(){ 133 input(); 134 int maxvalue; 135 vector<int > selection; 136 compute(maxvalue,selection); 137 cout<<"maxvalue:"<<maxvalue<<endl;//最终的结果 138 139 //一些输出 140 vector<int>::iterator t; 141 for(int i=0;i<=N;i++){ 142 for(int w=0;w<=W;w++){ 143 cout<<C[i][w]<<" "; 144 } 145 cout<<endl; 146 } 147 for(int i=0;i<=N;i++){ 148 for(int w=0;w<=W;w++){ 149 if(G[i][w]){ 150 cout<<" \\ "; 151 }else{ 152 cout<<" | "; 153 } 154 } 155 cout<<endl; 156 for(int w=0;w<=W;w++){ 157 if(G[i][w]){ 158 cout<<" v"; 159 }else{ 160 cout<<" v "; 161 } 162 } 163 cout<<endl; 164 } 165 166 for(t=selection.begin();t!=selection.end();t++){ 167 cout<<"in "<<*t<<endl; 168 } 169 }
以上是关于单个背包问题程序与感受(动态规划)的主要内容,如果未能解决你的问题,请参考以下文章