单个背包问题程序与感受(动态规划)

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 }

 

以上是关于单个背包问题程序与感受(动态规划)的主要内容,如果未能解决你的问题,请参考以下文章

01背包问题与动态规划(DP)

动态规划与背包问题

虾扯编程4——动态规划与背包问题

动态规划之01背包问题(含代码C)

动态规划背包问题总结:01完全多重与其二进制优化分组背包 题解与模板

动态规划基本思想