问题提出:
给定 n种物品和一背包, 物品的重量是 wi, 体积为 bi, 价值为 vi, 背包的容量为 C, 容积为 D, 问应如何选择装入背包中的物品, 使得装入背包中物品的总价值最大? 在选择装入背包的物品时, 对每种物品 i 只有两种选择, 即装入背包或不装入背包。不能将物品 i 装入背包多次, 也不能只装入部分物品 i。
算法分析:
0-1背包问题的两种扩展形式及其解法.rar
代码实现:
Code
1![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**//* 0-背包问题扩展
2
* By Flouse@2008年12月9日 17时06分28秒
3
*/
4
using System;
5
using System.Collections.Generic;
6
using System.Text;
7![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
8
namespace YourNameSpace // 修改为统一的命名空间
9![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![ContractedBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
10![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>装车类</summary>
11
public class Loading
12![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
13![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>货车载重量(t)</summary>
14
private int capacity;
15![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>货车体积容量(m3)</summary>
16
private int cubage;
17![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>最优(运费最高)装载清单</summary>
18
private List<string> optimizedBills = new List<string>();
19
public float totalPrice;
20![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
21![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>运单信息(装载相关)</summary>
22
public struct TranBill
23![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
24![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>托运单号</summary>
25
public string tranID;
26![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>拆单号</summary>
27
public int tranSplitID;
28![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>重量(t),实际运算里四舍五入化整</summary>
29
public float billWeight;
30![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>体积(m3),实际运算里四舍五入化整</summary>
31
public float billVolumn;
32![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>运费</summary>
33
public float tranPrice;
34
};
35![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
36![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>初始化货车信息</summary>
37
/// <param name="capacity">货车载重量(t)</param>
38
/// <param name="cubage">货车体积容量(m3)</param>
39
Loading(int capacity, int cubage)
40![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
41
this.capacity = capacity;
42
this.cubage = cubage;
43
}
44
~Loading()
45![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
46
GC.Collect();
47
//?? 释放内存
48
}
49![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>求解最优装车方案</summary>
50
/// <param name="tbs">待运的托运单</param>
51
/// <param name="mode">重量、体积转整模式
52
/// <value>0.0f~1.0f, 当 mode = 0.5f 时,即为四舍五入方式;当 mode = 0.0f 时, 即为最贪婪方式;当 mode = 1.0f 时,即为最保险方式</value>
53
/// <example>(int)(billWeight + mode), (int)(billVolumn + mode)</example>
54
/// </param>
55
/// <returns></returns>
56
public List<string> doLoad(TranBill[] tbs, float mode)
57![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
58
int count = tbs.Length;
59
int[] w = new int[count + 1];
60
int[] v = new int[count + 1];
61
float[] p = new float[count + 1];
62
float[, ,] m = new float[count + 1, capacity + 1, cubage + 1];
63
for (int i = 1; i <= count; i++)
64![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
65
w[i] = (int)(tbs[i - 1].billWeight + mode);
66
v[i] = (int)(tbs[i - 1].billVolumn + mode);
67
p[i] = tbs[i - 1].tranPrice;
68
}
69
Knapsack(p, w, v, count, m);
70
Trackback(m, w, v, tbs);
71
return optimizedBills;
72
}
73![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
74
private void Trackback(float[, ,] m, int[] w, int[] v, TranBill[] tbs)
75![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
76
int _capacity = capacity, _cubage = cubage, n = tbs.Length;
77
optimizedBills.Clear();
78
for (int i = 1; i < n; i++)
79![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
80
if (m[i, _capacity, _cubage] - m[i + 1, _capacity, _cubage] > 0.000001f)
81![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
82
optimizedBills.Add(tbs[i - 1].tranID + '.' + tbs[i-1].tranSplitID);
83
_capacity -= w[i];
84
_cubage -= v[i];
85
}
86
}
87
if (m[n, _capacity, _cubage] > 0) optimizedBills.Add(tbs[n - 1].tranID + '.' + tbs[n - 1].tranSplitID);
88
}
89![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
90![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>采用动态规划标记法(0-1背包问题算法)</summary>
91
/// <param name="p"></param>
92
/// <param name="w"></param>
93
/// <param name="v"></param>
94
/// <param name="n"></param>
95
/// <param name="m"></param>
96
private void Knapsack(float[] p, int[] w, int[] v, int n, float[, ,] m)
97![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
98
int wMax = Math.Min(w[n] - 1, capacity);
99
int vMax = Math.Min(v[n] - 1, cubage);
100![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
101
int i, j, k;
102![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
103
for (i = 0, j = 0; i <= wMax; i++)
104
for (j = 0; j < cubage; j++)
105
m[n, i, j] = 0;
106
for (j = 0; j <= vMax; j++)
107
for (i = wMax+1; i < capacity; i++)
108
m[n, i, j] = 0;
109![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
110
for (i = w[n]; i <= capacity; i++)
111
for (j = v[n]; j <= cubage; j++)
112
m[n, i, j] = p[n];
113![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
114
for (k = n - 1; k > 1; k--)
115![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
116
wMax = Math.Min(w[k] - 1, capacity);
117
vMax = Math.Min(v[k] - 1, cubage);
118![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
119
for (i = 0, j = 0; i <= wMax; i++)
120
for (j = 0; j < cubage; j++)
121
m[k, i, j] = m[k + 1, i, j];
122
for (j = 0; j <= vMax; j++)
123
for (i = wMax+1; i < capacity; i++)
124
m[k, i, j] = m[k + 1, i, j];
125![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
126
for (i = w[k]; i <= capacity; i++)
127
for (j = v[k]; j <= cubage; j++)
128
m[k, i, j] = Math.Max(m[k + 1, i, j], m[k + 1, i - w[k], j - v[k]] + p[k]);
129
}
130
m[1, capacity, cubage] = m[2, capacity, cubage];
131
if (capacity >= w[1] && cubage >= v[1]) m[1, capacity, cubage] = Math.Max(m[1, capacity, cubage], m[2, capacity - w[1], cubage - v[1]] + p[1]);
132![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
133
totalPrice = m[1, capacity, cubage];
134
}
135![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
136
// 回溯法,示实现
137
//class BackBag{
138
//public:
139
// BackBag(int W){
140
// maxW = W;
141
// ac = maxValue = nowValue = 0;
142
// }
143
// void KnapSack(int v[], int c[], bool used[], int n){ //回溯法
144
// for (int i = 0; i < n; i++){
145
// nowValue += v[i];
146
// ac += c[i];
147
// used[i] = true;
148
// }
149
// search(0, v, c, used, n);
150
// }
151
// void search(int i, int v[], int c[], bool used[], int n){
152
// if (i==n) return;
153
// if (nowValue <= maxValue) return;
154
// if (ac <= maxW){
155
// maxValue = nowValue;
156
// return;
157
// }
158
// nowValue -= v[i];
159
// ac -= c[i];
160
// used[i] = false;
161
// search(i+1, v, c, used, n); //考虑不取i
162
// nowValue += v[i];
163
// ac += c[i];
164
// used[i] = true;
165
// search(i+1, v, c, used, n); //考虑取i
166
// }
167
// int getMaxV(){
168
// return maxValue;
169
// }
170
//private:
171
// int maxW; //背包所能承受的重量
172
// int ac;
173
// int maxValue;
174
// int nowValue;
175
//};
176![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
177![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>调用示例</summary>
178
/// <param name="args"></param>
179
static void Main(string[] args)
180![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
181
Loading l = new Loading(5, 5); // 设置货车的重容和体容
182![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
183
int n = Convert.ToInt32(Console.ReadLine());
184
TranBill[] tranBills = new TranBill[n];
185
string inStream;
186
for (int i = 0; i < n; i++)
187![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
188
inStream = Console.ReadLine();
189
string[] temp = inStream.Split('\t');
190
tranBills[i].tranID = temp[0];
191
tranBills[i].tranSplitID = int.Parse(temp[1]);
192
tranBills[i].billWeight = float.Parse(temp[2]);
193
tranBills[i].billVolumn = float.Parse(temp[3]);
194
tranBills[i].tranPrice = float.Parse(temp[4]);
195
}
196
List<string> optimizedBills = l.doLoad(tranBills, 0.5f); // 执行最优装载求解
197
Console.WriteLine(l.totalPrice); // 最大托运费
198
foreach (string s in optimizedBills) // 装载序列
199![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
200
Console.Write(s + '\t');
201
}
202
}
203
}
204
}
205![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
206![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**//* 示例输入
207
5
208
tran 1 1 1 100
209
tran 2 1 1 100
210
tran 3 1 1 100
211
tran 4 1 1 100
212
tran 5 1 1 100
213
*/