0/1背包问题的分支定界法算法

本文介绍了一种使用分支定界法解决背包问题的具体实现,包括定义数据结构、队列操作、排序、求解最大最小可能值等步骤,并通过一个实例展示了如何找到最优解。
  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #define MAXNUM 100
  4. struct node{
  5. int step;
  6. double price;
  7. double weight;
  8. double max, min;
  9. unsigned long po;
  10. };
  11. typedef struct node DataType;
  12. struct SeqQueue { /* 顺序队列类型定义 */
  13. int f, r;
  14. DataType q[MAXNUM];
  15. };
  16. typedef struct SeqQueue *PSeqQueue;
  17. PSeqQueue createEmptyQueue_seq( void ) {
  18. PSeqQueue paqu;
  19. paqu = (PSeqQueue)malloc(sizeof(struct SeqQueue));
  20. if (paqu == NULL)
  21. printf("Out of space!! /n");
  22. else
  23. paqu->f = paqu->r = 0;
  24. return paqu;
  25. }
  26. int isEmptyQueue_seq( PSeqQueue paqu ) {
  27. return paqu->f == paqu->r;
  28. }
  29. /* 在队列中插入一元素x */
  30. void enQueue_seq( PSeqQueue paqu, DataType x ) {
  31. if( (paqu->r + 1) % MAXNUM == paqu->f )
  32. printf( "Full queue./n" );
  33. else {
  34. paqu->q[paqu->r] = x;
  35. paqu->r = (paqu->r + 1) % MAXNUM;
  36. }
  37. }
  38. /* 删除队列头元素 */
  39. void deQueue_seq( PSeqQueue paqu ) {
  40. if( paqu->f == paqu->r )
  41. printf( "Empty Queue./n" );
  42. else
  43. paqu->f = (paqu->f + 1) % MAXNUM;
  44. }
  45. /* 对非空队列,求队列头部元素 */
  46. DataType frontQueue_seq( PSeqQueue paqu ) {
  47. return (paqu->q[paqu->f]);
  48. }
  49. /* 物品按性价比从新排序*/
  50. void sort(int n, double p[], double w[]){
  51. int i, j;
  52. for (i = 0; i < n-1; i++)
  53. for (j = i; j < n-1; j++) {
  54. double a = p[j]/w[j];
  55. double b = p[j+1]/w[j+1];
  56. if (a < b) {
  57. double temp = p[j];
  58. p[j] = p[j+1];
  59. p[j+1] = temp;
  60. temp = w[j];
  61. w[j] = w[j+1];
  62. w[j+1] = temp;
  63. }
  64. }
  65. }
  66. /* 求最大可能值*/
  67. double up(int k, double m, int n, double p[], double w[]){
  68. int i = k;
  69. double s = 0;
  70. while (i < n && w[i] < m) {
  71. m -= w[i];
  72. s += p[i];
  73. i++;
  74. }
  75. if (i < n && m > 0) {
  76. s += p[i] * m / w[i];
  77. i++;
  78. }
  79. return s;
  80. }
  81. /* 求最小可能值*/
  82. double down(int k, double m, int n, double p[], double w[]){
  83. int i = k;
  84. double s = 0;
  85. while (i < n && w[i] <= m) {
  86. m -= w[i];
  87. s += p[i];
  88. i++;
  89. }
  90. return s;
  91. }
  92. /* 用队列实现分支定界算法*/
  93. double solve(double m, int n, double p[], double w[], unsigned long* po){
  94. double min;
  95. PSeqQueue q = createEmptyQueue_seq();
  96. DataType x = {0,0,0,0,0,0};
  97. sort(n, p, w);
  98. x.max = up(0, m, n, p, w);
  99. x.min = min = down(0, m, n, p, w);
  100. if (min == 0) return -1;
  101. enQueue_seq(q, x);
  102. while (!isEmptyQueue_seq(q)){
  103. int step;
  104. DataType y;
  105. x = frontQueue_seq(q);
  106. deQueue_seq(q);
  107. if (x.max < min) continue;
  108. step = x.step + 1;
  109. if (step == n+1) continue;
  110. y.max = x.price + up(step, m - x.weight, n, p, w);
  111. if (y.max >= min) {
  112. y.min = x.price + down(step, m-x.weight, n, p, w);
  113. y.price = x.price;
  114. y.weight = x.weight;
  115. y.step = step;
  116. y.po = x.po << 1;
  117. if (y.min >= min) {
  118. min = y.min;
  119. if (step == n) *po = y.po;
  120. }
  121. enQueue_seq(q, y);
  122. }
  123. if (x.weight + w[step-1] <= m) {
  124. y.max = x.price + p[step-1] +
  125. up(step, m-x.weight-w[step-1], n, p, w);
  126. if (y.max >= min) {
  127. y.min = x.price + p[step-1] +
  128. down(step, m-x.weight-w[step-1], n, p, w);
  129. y.price = x.price + p[step-1];
  130. y.weight = x.weight + w[step-1];
  131. y.step = step;
  132. y.po = (x.po << 1) + 1;
  133. if (y.min >= min) {
  134. min = y.min;
  135. if (step == n) *po = y.po;
  136. }
  137. enQueue_seq(q, y);
  138. }
  139. }
  140. }
  141. return min;
  142. }
  143. #define n 4
  144. double m = 15;
  145. double p[n] = {10, 10, 12, 18};
  146. double w[n] = {2, 4, 6, 9};
  147. int main() {
  148. int i;
  149. double d;
  150. unsigned long po;
  151. d = solve(m, n, p, w, &po);
  152. if (d == -1)
  153. printf("No solution!/n");
  154. else {
  155. for (i = 0; i < n; i++)
  156. printf("x%d is %d/n", i + 1, ((po & (1<<(n-i-1))) != 0));
  157. printf("The max weight is %f/n", d);
  158. }
  159. getchar();
  160. return 0;
  161. }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值