1、 问题描述有一批共个集装箱要装上 2 艘载重量分别为 C1 和 C2 的轮船,其中集装箱 i 的重量为 Wi,且 装载问题要求确定是否有一个合理的装载方案可将这个集装箱装上这 2 艘轮船。如果有,找出一种装载方案。 容易证明:如果一个给定装载问题有解,则采用下面的策略可得到最优装载方案。 (1)首先将第一艘轮船尽可能装满;(2)将剩余的集装箱装上第二艘轮船。 1、队列式分支限界法求解在算法的循环体中,首先检测当前扩展结点的左儿子结点是否为可行结点。如果是则将其加入到活结点队列中。然后将其右儿子结点加入到活结点队列中(右儿子结点一定是可行结点)。2 个儿子结点都产生后,当前扩展结点被舍弃。活结点
2、队列中的队首元素被取出作为当前扩展结点,由于队列中每一层结点之后都有一个尾部标记-1,故在取队首元素时,活结点队列一定不空。当取出的元素是-1 时,再判断当前队列是否为空。如果队列非空,则将尾部标记-1 加入活结点队列,算法开始处理下一层的活结点。节点的左子树表示将此集装箱装上船,右子树表示不将此集装箱装上船。设 bestw 是当前最优解; ew 是当前扩展结点所相应的重量;r是剩余集装箱的重量。则当 ew+r 2. using namespace std; 3. 4. template 5. class Queue 6. 7. public: 8. Queue(int MaxQueueSiz
3、e=50); 9. Queue()delete queue; 10. bool IsEmpty()constreturn front=rear; 11. bool IsFull()return ( ( (rear+1) %MaxSize=front )?1:0); 12. T Top() const; 13. T Last() const; 14. Queue 15. Queue 16. Queue 17. void Output(ostream 18. int Length()return (rear-front); 19. private: 20. int front; 21. int r
4、ear; 22. int MaxSize; 23. T *queue; 24. ; 25. 26. template 27. Queue:Queue(int MaxQueueSize) 28. 29. MaxSize=MaxQueueSize+1; 30. queue=new TMaxSize; 31. front=rear=0; 32. 33. 34. template 35. T Queue:Top()const 36. 37. if(IsEmpty() 38. 39. cout 46. T Queue :Last()const 47. 48. if(IsEmpty() 49. 50. c
5、out 57. Queuei=(front+1)%MaxSize;i-) 97. out 101. ostreamreturn out; 2、6d3-1.cppcpp view plain copy1. /装载问题 队列式分支限界法求解 2. #include “stdafx.h“ 3. #include “Queue.h“ 4. #include 5. using namespace std; 6. 7. const int N = 4; 8. 9. template 10. class QNode 11. 12. template 13. friend void EnQueue(Queue
6、* 14. 15. template 16. friend Type MaxLoading(Type w,Type c,int n,int bestx); 17. 18. private: 19. QNode *parent; /指向父节点的指针 20. bool LChild; /左儿子标识 21. Type weight; /节点所相应的载重量 22. ; 23. 24. template 25. void EnQueue(Queue* 26. 27. template 28. Type MaxLoading(Type w,Type c,int n,int bestx); 29. 30.
7、int main() 31. 32. float c = 70; 33. float w = 0,20,10,26,15;/下标从 1 开始 34. int xN+1; 35. float bestw; 36. 37. cout 59. void EnQueue(Queue* 67. bestxn = ch; 68. 69. return; 70. 71. /非叶节点 72. QNode *b; 73. b = new QNode; 74. b-weight = wt; 75. b-parent = E; 76. b-LChild = ch; 77. Q.Add(b); 78. 79. 80.
8、 template 81. Type MaxLoading(Type w,Type c,int n,int bestx) 82. /队列式分支限界法,返回最优装载重量,bestx 返回最优解 83. /初始化 84. Queue* Q; /活节点队列 85. Q.Add(0); /同层节点尾部标识 86. int i = 1; /当前扩展节点所处的层 87. Type Ew = 0, /扩展节点所相应的载重量 88. bestw = 0, /当前最优装载重量 89. r = 0; /剩余集装箱重量 90. 91. for(int j=2; j *E = 0, /当前扩展节点 97. *best
9、E; /当前最优扩展节点 98. 99. /搜索子集空间树 100. while(true) 101. 102. /检查左儿子节点 103. Type wt = Ew + wi; 104. if(wt bestw) 107. 108. bestw = wt; 109. 110. EnQueue(Q,wt,i,n,bestw,E,bestE,bestx,true); 111. 112. 113. /检查右儿子节点 114. if(Ew+rbestw) 115. 116. EnQueue(Q,Ew,i,n,bestw,E,bestE,bestx,false); 117. 118. Q.Delete
10、(E);/取下一扩展节点 119. 120. if(!E)/同层节点尾部 121. 122. if(Q.IsEmpty() 123. 124. break; 125. 126. Q.Add(0); /同层节点尾部标识 127. Q.Delete(E); /取下一扩展节点 128. i+; /进入下一层 129. r-=wi; /剩余集装箱重量 130. 131. Ew =E-weight; /新扩展节点所对应的载重量 132. 133. 134. /构造当前最优解 135. for(int j=n-1; j0; j-) 136. 137. bestxj = bestE-LChild; 138.
11、 bestE = bestE-parent; 139. 140. return bestw; 141. 程序运行结果如图:2、优先队列式分支限界法求解解装载问题的优先队列式分支限界法用 最大优先队列 存储活结点表。活结点 x 在优先队列中的优先级定义为从根结点到结点 x 的路径所相应的载重量再加上剩余集装箱的重量之和。优先队列中优先级最大的活结点成为下一个扩展结点。以结点 x 为根的子树中所有结点相应的路径的载重量不超过它的优先级。子集树中叶结点所相应的载重量与其优先级相同。在优先队列式分支限界法中,一旦有一个叶结点成为当前扩展结点,则可以断言该叶结点所相应的解即为最优解。此时可终止算法。算法
12、具体代码实现如下:1、MaxHeap.hcpp view plain copy1. template 2. class MaxHeap 3. 4. public: 5. MaxHeap(int MaxHeapSize = 10); 6. MaxHeap() delete heap; 7. int Size() const return CurrentSize; 8. 9. T Max() 10. /查 11. if (CurrentSize = 0) 12. 13. throw OutOfBounds(); 14. 15. return heap1; 16. 17. 18. MaxHeap /
13、增 19. MaxHeap /删 20. 21. void Initialize(T a, int size, int ArraySize); 22. 23. private: 24. int CurrentSize, MaxSize; 25. T *heap; / element array 26. ; 27. 28. template 29. MaxHeap:MaxHeap(int MaxHeapSize) 30. / Max heap constructor. 31. MaxSize = MaxHeapSize; 32. heap = new TMaxSize+1; 33. Curren
14、tSize = 0; 34. 35. 36. template 37. MaxHeap / 父节点下降 52. i /= 2; / 继续向上,搜寻正确位置 53. 54. 55. heapi = x; 56. return *this; 57. 58. 59. template 60. MaxHeap / 是,i 就是 y 的正确位置,退出 88. 89. 90. / 否,需要继续向下,重整堆 91. heapi = heapci; / 大于父节点的孩子节点上升 92. i = ci; / 向下一层,继续搜索正确位置 93. ci *= 2; 94. 95. 96. heapi = y; 97
15、. return *this; 98. 99. 100. template 101. void MaxHeap:Initialize(T a, int size,int ArraySize) 102. / Initialize max heap to array a. 103. delete heap; 104. heap = a; 105. CurrentSize = size; 106. MaxSize = ArraySize; 107. 108. / 从最后一个内部节点开始,一直到根,对每个子树进行堆重整 109. for (int i = CurrentSize/2; i = 1; i
16、-) 110. 111. T y = heapi; / 子树根节点元素 112. / find place to put y 113. int c = 2*i; / parent of c is target 114. / location for y 115. while (c = heapc) 124. 125. break; / yes 126. 127. 128. / no 129. heapc/2 = heapc; / move child up 130. c *= 2; / move down a level 131. 132. heapc/2 = y; 133. 134. 2、6
17、d3-2.cppcpp view plain copy1. /装载问题 优先队列式分支限界法求解 2. #include “stdafx.h“ 3. #include “MaxHeap.h“ 4. #include 5. using namespace std; 6. 7. const int N = 4; 8. 9. class bbnode; 10. 11. template 12. class HeapNode 13. 14. template 15. friend void AddLiveNode(MaxHeap 16. template 17. friend Type MaxLoad
18、ing(Type w,Type c,int n,int bestx); 18. public: 19. operator Type() constreturn uweight; 20. private: 21. bbnode *ptr; /指向活节点在子集树中相应节点的指针 22. Type uweight; /活节点优先级(上界) 23. int level; /活节点在子集树中所处的层序号 24. ; 25. 26. class bbnode 27. 28. template 29. friend void AddLiveNode(MaxHeap 30. template 31. frie
19、nd Type MaxLoading(Type w,Type c,int n,int bestx); 32. friend class AdjacencyGraph; 33. 34. private: 35. bbnode *parent; /指向父节点的指针 36. bool LChild; /左儿子节点标识 37. ; 38. 39. template 40. void AddLiveNode(MaxHeap 41. 42. template 43. Type MaxLoading(Type w,Type c,int n,int bestx); 44. 45. 46. int main()
20、 47. 48. float c = 70; 49. float w = 0,20,10,26,15;/下标从 1 开始 50. int xN+1; 51. float bestw; 52. 53. cout 75. void AddLiveNode(MaxHeap 78. b-parent = E; 79. b-LChild = ch; 80. HeapNode N; 81. 82. N.uweight = wt; 83. N.level = lev; 84. N.ptr = b; 85. H.Insert(N); 86. 87. 88. /优先队列式分支限界法,返回最优载重量,bestx
21、返回最优解 89. template 90. Type MaxLoading(Type w,Type c,int n,int bestx) 91. 92. /定义最大的容量为 1000 93. MaxHeap H(1000); 94. 95. /定义剩余容量数组 96. Type *r = new Typen+1; 97. rn = 0; 98. 99. for(int j=n-1; j0; j-) 100. 101. rj = rj+1 + wj+1; 102. 103. 104. /初始化 105. int i = 1;/当前扩展节点所处的层 106. bbnode *E = 0;/当前扩
22、展节点 107. Type Ew = 0; /扩展节点所相应的载重量 108. 109. /搜索子集空间树 110. while(i!=n+1)/非叶子节点 111. 112. /检查当前扩展节点的儿子节点 113. if(Ew+wi N; 122. H.DeleteMax(N);/非空 123. i = N.level; 124. E = N.ptr; 125. Ew = N.uweight - ri-1; 126. 127. 128. /构造当前最优解 129. for(int j=n; j0; j-) 130. 131. bestxj = E-LChild; 132. E = E-parent; 133. 134. 135. return Ew; 136. 程序运行结果如图: