• 用队列式广度优先算法解决背包问题


    一 问题描述

    有一个背包和 4 个物品,每个物品的重量和价值都如下图所示,背包的容量 W=10,求在不超过背包容量的前提下,把哪些物品放入背包才能获得最大价值。

    二 实现

    1. package com.platform.modules.alg.alglib.p932;
    2. import java.util.LinkedList;
    3. import java.util.Queue;
    4. public class P932 {
    5. public String output = "";
    6. public static final int N = 10;
    7. boolean bestx[] = new boolean[N];
    8. Goods goods[] = new Goods[N];
    9. Integer bestp;
    10. int W;
    11. int n;
    12. int sumw;
    13. int sumv;
    14. public String cal(String input) {
    15. String[] line = input.split("\n");
    16. String[] words = line[0].split(" ");
    17. // 物品的个数和背包的容量
    18. n = Integer.parseInt(words[0]);
    19. W = Integer.parseInt(words[1]);
    20. bestp = 0; // bestv 用来记录最优解
    21. sumw = 0; // sumw 为所有物品的总重量。
    22. sumv = 0; // sumv为所有物品的总价值
    23. words = line[1].split(" ");
    24. for (int i = 1; i <= words.length / 2; i++) { // 输入每个物品的重量和价值,用空格分开
    25. goods[i].weight = Integer.parseInt(words[2 * i - 2]);
    26. goods[i].value = Integer.parseInt(words[2 * i - 1]);
    27. sumw += goods[i].weight;
    28. sumv += goods[i].value;
    29. }
    30. if (sumw <= W) {
    31. bestp = sumv;
    32. output = bestp.toString();
    33. return output;
    34. }
    35. bfs();
    36. output += bestp.toString() + "\n";
    37. for (int i = 1; i <= n; i++) { // 输出最优解
    38. if (bestx[i])
    39. output += i + " ";
    40. }
    41. return output;
    42. }
    43. public P932() {
    44. for (int i = 0; i < goods.length; i++) {
    45. goods[i] = new Goods();
    46. }
    47. }
    48. int bfs() { // 队列式分支限界法
    49. int t, tcp, trp, trw; // 当前处理的物品序号t,装入背包物品价值 tcp,剩余容量 trw
    50. Queue q = new LinkedList<>(); // 创建一个普通队列(先进先出)
    51. q.add(new Node(0, sumv, W, 1)); // 压入一个初始节点
    52. while (!q.isEmpty()) {
    53. // 定义三个结点型变量
    54. Node livenode = new Node();
    55. Node lchild = new Node();
    56. Node rchild = new Node();
    57. livenode = q.peek(); // 取出队头元素作为当前扩展结点 livenode
    58. q.poll(); // 队头元素出队
    59. t = livenode.id; // 当前处理的物品序号
    60. // 搜到最后一个物品的时候不需要往下搜索
    61. // 如果当前的背包没有剩余容量(已经装满)了,不再扩展
    62. if (t > n || livenode.rw == 0) {
    63. if (livenode.cp >= bestp) { // 更新最优解和最优值
    64. for (int i = 1; i <= n; i++)
    65. bestx[i] = livenode.x[i];
    66. bestp = livenode.cp;
    67. }
    68. continue;
    69. }
    70. if (livenode.cp + livenode.rp < bestp) // 判断当前结点是否满足限界条件,如果不满足不再扩展
    71. continue;
    72. tcp = livenode.cp; // 当前背包中的价值
    73. trp = livenode.rp - goods[t].value; // 不管当前物品装入与否,剩余价值都会减少。
    74. trw = livenode.rw; //背包剩余容量
    75. if (trw >= goods[t].weight) { //扩展左孩子,满足约束条件,可以放入背包
    76. lchild.rw = trw - goods[t].weight;
    77. lchild.cp = tcp + goods[t].value;
    78. lchild = new Node(lchild.cp, trp, lchild.rw, t + 1);
    79. for (int i = 1; i < t; i++) // 复制以前的解向量
    80. lchild.x[i] = livenode.x[i];
    81. lchild.x[t] = true;
    82. if (lchild.cp > bestp) // 比最优值大才更新
    83. bestp = lchild.cp;
    84. q.add(lchild); // 左孩子入队
    85. }
    86. if (tcp + trp >= bestp) {//扩展右孩子,满足限界条件,不放入背包
    87. rchild = new Node(tcp, trp, trw, t + 1);
    88. for (int i = 1; i < t; i++)//复制以前的解向量
    89. rchild.x[i] = livenode.x[i];
    90. rchild.x[t] = false;
    91. q.add(rchild); // 右孩子入队
    92. }
    93. }
    94. return bestp;// 返回最优值
    95. }
    96. }
    97. // 定义结点。每个节点来记录当前的解。
    98. class Node {
    99. int cp; // cp 为当前装入背包的物品总价值
    100. int rp; // rp为剩余物品的总价值
    101. int rw; // 剩余容量
    102. int id; // 物品号
    103. boolean x[] = new boolean[P932.N]; //解向量
    104. Node() {
    105. }
    106. Node(int _cp, int _rp, int _rw, int _id) {
    107. cp = _cp;
    108. rp = _rp;
    109. rw = _rw;
    110. id = _id;
    111. }
    112. }
    113. // 物品
    114. class Goods {
    115. int weight; //重量
    116. int value; //价值
    117. }

    三 测试

  • 相关阅读:
    凛冬已至,望各位早日背上行囊出发
    排序算法-----归并排序
    计算机前沿(从三次数学危机到量子计算)
    移动app安全检测报告有什么作用?
    Zookeeper的会话管理和读写流程
    Laravel 完整开源项目大全
    如何从手动测试转到自动化测试?(附有自动化测试学习路线)
    sqlx库使用指南
    基于SpringBoot+Vue的婚恋相亲交友系统
    基于RSSI的室内wifi定位系统 计算机竞赛
  • 原文地址:https://blog.csdn.net/chengqiuming/article/details/126432168