Java实现优先队列式广度优先搜索算法的示例代码

目录
  • 1.问题描述
  • 2.实现
  • 3.测试

1.问题描述

2.实现

package com.platform.modules.alg.alglib.p933;

import java.util.Arrays;
import java.util.PriorityQueue;

public class P933 {
    public static final int N = 10;
    // 记录最优解
    boolean bestx[] = new boolean[N];
    // 辅助数组,用于存储排序后的重量和价值
    private int w[] = new int[N];
    private int v[] = new int[N];
    Goods goods[] = new Goods[N];
    Object S[] = new Object[N];
    // 用来记录最优解
    Integer bestp;
    // 为背包的最大容量
    int W;
    // 为物品的个数。
    int n;
    // 为所有物品的总重量。
    int sumw;
    // 为所有物品的总价值
    int sumv;
    public String output = "";

    public P933() {
        for (int i = 0; i < goods.length; i++) {
            goods[i] = new Goods();
        }
        for (int i = 0; i < S.length; i++) {
            S[i] = new Object();
        }
    }

    // 计算节点的上界
    double Bound(Node tnode) {
        // 已装入背包物品价值
        double maxvalue = tnode.cp;
        int t = tnode.id; // 排序后序号
        double left = tnode.rw; // 剩余容量
        while (t <= n && w[t] <= left) {
            maxvalue += v[t];
            left -= w[t++];
        }
        if (t <= n)
            maxvalue += ((double) (v[t])) / w[t] * left;
        return maxvalue;
    }

    public String cal(String input) {

        String[] line = input.split("\n");
        String[] words = line[0].split(" ");
        // 物品的个数和背包的容量
        n = Integer.parseInt(words[0]);
        W = Integer.parseInt(words[1]);
        bestp = 0; // 用来记录最优解
        sumw = 0; // sumw 为所有物品的总重量。
        sumv = 0; // sumv为所有物品的总价值

        words = line[1].split(" ");
        for (int i = 1; i <= words.length / 2; i++) { // 输入每个物品的重量和价值,用空格分开
            goods[i].weight = Integer.parseInt(words[2 * i - 2]);
            goods[i].value = Integer.parseInt(words[2 * i - 1]);
            sumw += goods[i].weight;
            sumv += goods[i].value;
            S[i - 1].id = i;
            S[i - 1].d = 1.0 * goods[i].value / goods[i].weight;
        }
        if (sumw <= W) {
            bestp = sumv;
            output = bestp.toString();
            return output;
        }
        Arrays.sort(S); // 按价值重量比非递增排序
        for (int i = 1; i <= n; i++) {//把排序后的数据传递给辅助数组
            w[i] = goods[S[i - 1].id].weight;
            v[i] = goods[S[i - 1].id].value;
        }
        priorbfs();//优先队列分支限界法
        output += bestp + "\n";

        for (int i = 1; i <= n; i++) { // 输出最优解
            if (bestx[i])
                output += S[i - 1].id + " "; // 输出原物品序号(排序前的)
        }
        return output;
    }

    // 优先队列式分支限界法
    int priorbfs() {
        // 当前处理的物品序号t,当前装入背包物品价值tcp,当前剩余容量trw
        int t, tcp, trw;
        double tup;  // 当前价值上界 tup
        PriorityQueue<Node> q = new PriorityQueue<>(); // 优先队列

        q.add(new Node(0, sumv, W, 1)); // 初始化,根结点加入优先队列
        while (!q.isEmpty()) {
            // 定义三个结点型变量
            Node livenode;
            Node lchild = new Node();
            Node rchild = new Node();
            livenode = q.peek(); // 取出队头元素作为当前扩展结点 livenode
            q.poll(); // 队头元素出队
            t = livenode.id; // 当前处理的物品序号
            // 搜到最后一个物品的时候不需要往下搜索。
            // 如果当前的背包没有剩余容量(已经装满)了,不再扩展。
            if (t > n || livenode.rw == 0) {
                if (livenode.cp >= bestp) { // 更新最优解和最优值
                    for (int i = 1; i <= n; i++)
                        bestx[i] = livenode.x[i];
                    bestp = livenode.cp;
                }
                continue;
            }
            if (livenode.up < bestp)//如果不满足不再扩展
                continue;
            tcp = livenode.cp; //当前背包中的价值
            trw = livenode.rw; //背包剩余容量
            if (trw >= w[t]) { //扩展左孩子,满足约束条件,可以放入背包
                lchild.cp = tcp + v[t];
                lchild.rw = trw - w[t];
                lchild.id = t + 1;
                tup = Bound(lchild); //计算左孩子上界
                lchild = new Node(lchild.cp, tup, lchild.rw, lchild.id);
                for (int i = 1; i <= n; i++)//复制以前的解向量
                    lchild.x[i] = livenode.x[i];
                lchild.x[t] = true;
                if (lchild.cp > bestp)//比最优值大才更新
                    bestp = lchild.cp;
                q.add(lchild);//左孩子入队
            }
            rchild.cp = tcp;
            rchild.rw = trw;
            rchild.id = t + 1;
            tup = Bound(rchild);//计算右孩子上界
            if (tup >= bestp) {//扩展右孩子,满足限界条件,不放入
                rchild = new Node(tcp, tup, trw, t + 1);
                for (int i = 1; i <= n; i++)//复制以前的解向量
                    rchild.x[i] = livenode.x[i];
                rchild.x[t] = false;
                q.add(rchild);//右孩子入队
            }
        }
        return bestp;//返回最优值。
    }
}

// 定义结点。每个节点来记录当前的解。
class Node implements Comparable<Node> {
    int cp; // cp 为当前装入背包的物品总价值
    double up; // 价值上界
    int rw; //  剩余容量
    int id; // 物品号
    boolean x[] = new boolean[P933.N]; // 解向量

    Node() {
    }

    Node(int _cp, double _up, int _rw, int _id) {
        cp = _cp;
        up = _up;
        rw = _rw;
        id = _id;
    }

    @Override
    public int compareTo(Node o) {
        return (this.up - o.up) > 0 ? 1 : -1;
    }
}

// 物品
class Goods {
    int weight; // 重量
    int value; // 价值
}

// 辅助物品结构体,用于按单位重量价值(价值/重量比)排序
class Object implements Comparable {
    int id; // 序号
    double d; // 单位重量价值

    @Override
    public int compareTo(java.lang.Object o) {
        return this.d > ((Object) o).d ? -1 : 1;
    }
}

3.测试

到此这篇关于Java实现优先队列式广度优先搜索算法的示例代码的文章就介绍到这了,更多相关Java广度优先搜索算法内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java利用广度优先搜索实现抓牛问题

    目录 一.原问题链接 二.输入和输出 三.输入和输出样例 四.代码 五.测试 一.原问题链接 http://poj.org/problem?id=3278 二.输入和输出 1.输入 两个数,第1个数代表农夫的位置,第2个数代表牛的位置 2.输出 农夫抓牛的最小步数 三.输入和输出样例 1.输入样例 5 17 2.输出样例 4 四.代码 package graph.poj3278; import java.util.LinkedList; import java.util.Queue; impor

  • Java数据结构优先队列实练

    目录 最后一块石头的重量 题目描述 思路详解 代码与结果 装满杯子需要的最短总时长 题目描述 思路详解 代码与结果 移除石子的最大得分 题目描述 思路详解 代码与结果 最后一块石头的重量 题目描述 思路详解 这里采用最大堆进行解题. 我们首先考虑,每次拿出两个最大的进行比较,然后大的减去小的重新放入不就完成了嘛. 首先我们创建一个优先队列,遍历重量,放入队列.依次取出重量最大的和第二大的,如果a>b就把a-b重新放入.直到队列里面的元素只剩1个的时候,输出结果. 代码与结果 class Solu

  • Java实现二叉树的深度优先遍历和广度优先遍历算法示例

    本文实例讲述了Java实现二叉树的深度优先遍历和广度优先遍历算法.分享给大家供大家参考,具体如下: 1. 分析 二叉树的深度优先遍历的非递归的通用做法是采用栈,广度优先遍历的非递归的通用做法是采用队列. 深度优先遍历:对每一个可能的分支路径深入到不能再深入为止,而且每个结点只能访问一次.要特别注意的是,二叉树的深度优先遍历比较特殊,可以细分为先序遍历.中序遍历.后序遍历.具体说明如下: 先序遍历:对任一子树,先访问根,然后遍历其左子树,最后遍历其右子树. 中序遍历:对任一子树,先遍历其左子树,然

  • 深度优先与广度优先Java实现代码示例

    在编程生活中,我们总会遇见树性结构,这几天刚好需要对树形结构操作,就记录下自己的操作方式以及过程.现在假设有一颗这样树,(是不是二叉树都没关系,原理都是一样的) 1.深度优先 英文缩写为DFS即Depth First Search. 深度优先搜索是一种在开发爬虫早期使用较多的方法.它的目的是要达到被搜索结构的叶结点(即那些不包含任何超链的HTML文件) .在一个HTML文件中,当一个超链被选择后,被链接的HTML文件将执行深度优先搜索,即在搜索其余的超链结果之前必须先完整地搜索单独的一条链.深度

  • Java优先队列 priority queue

    目录 1.优先队列概念 2.二叉堆(Heap) 完全二叉树和满二叉树 堆的重要操作 1.优先队列概念 优先队列(priority queue)是一种特殊的数据结构. 队列中每一个元素都被分配到一个优先权值,出队顺序按照优先权值来划分. 一般有两种出队顺序:高优先权出队或低优先权出队. priority queue至少要有两个最基本的ADT:进队,出队(按照高优先权或低优先权) 产生原因:同样是为了提高数据处理的效率.试想,要实现优先队列对应的功能,若使用链表或者数组,那么要么先排序再插入,要么先

  • Java的优先队列PriorityQueue原理及实例分析

    这篇文章主要介绍了Java的优先队列PriorityQueue原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一.优先队列概述 优先队列PriorityQueue是Queue接口的实现,可以对其中元素进行排序, 可以放基本数据类型的包装类(如:Integer,Long等)或自定义的类 对于基本数据类型的包装器类,优先队列中元素默认排列顺序是升序排列 但对于自己定义的类来说,需要自己定义比较器 二.常用方法 peek()//返回队首元素

  • Java实现优先队列式广度优先搜索算法的示例代码

    目录 1.问题描述 2.实现 3.测试 1.问题描述 2.实现 package com.platform.modules.alg.alglib.p933; import java.util.Arrays; import java.util.PriorityQueue; public class P933 { public static final int N = 10; // 记录最优解 boolean bestx[] = new boolean[N]; // 辅助数组,用于存储排序后的重量和价

  • Java实现8种排序算法的示例代码

    冒泡排序 O(n2) 两个数比较大小,较大的数下沉,较小的数冒起来. public static void bubbleSort(int[] a) { //临时变量 int temp; //i是循环次数,也是冒泡的结果位置下标,5个数组循环5次 for (int i = 0; i < a.length; i++) { //从最后向前面两两对比,j是比较中下标大的值 for (int j = a.length - 1; j > i; j--) { //让小的数字排在前面 if (a[j] <

  • Java用邻接表存储图的示例代码

    目录 一.点睛 1.无向图 2.无向图的链接表 3.说明 4.无向图 二.邻接表的数据结构 1.节点 2.邻接点 三.算法步骤 四.实现 五.测试 一.点睛 邻接表是图的一种链式存储方法,其数据结构包括两部分:节点和邻接点. 用邻接表可以表示无向图,有向图和网.在此用无向图进行说明. 1.无向图 2.无向图的链接表 3.说明 节点 a 的邻接点是节点 b.d,其邻接点的存储下标为1.3,按照头插法(逆序)将其放入节点 a 后面的单链表中. 节点 b 的邻接点是节点 a.c.d,其邻接点的存储下标

  • Java利用Redis实现消息队列的示例代码

    本文介绍了Java利用Redis实现消息队列的示例代码,分享给大家,具体如下: 应用场景 为什么要用redis? 二进制存储.java序列化传输.IO连接数高.连接频繁 一.序列化 这里编写了一个java序列化的工具,主要是将对象转化为byte数组,和根据byte数组反序列化成java对象; 主要是用到了ByteArrayOutputStream和ByteArrayInputStream; 注意:每个需要序列化的对象都要实现Serializable接口; 其代码如下: package Utils

  • Java实现动态获取图片验证码的示例代码

    本文介绍了Java实现动态获取图片验证码的示例代码,分享给大家,具体如下: import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.UnsupportedEncodingEx

  • Java使用sftp定时下载文件的示例代码

    sftp简介 sftp是Secure File Transfer Protocol的缩写,安全文件传送协议.可以为传输文件提供一种安全的网络的加密方法.sftp 与 ftp 有着几乎一样的语法和功能.SFTP 为 SSH的其中一部分,是一种传输档案至 Blogger 伺服器的安全方式.其实在SSH软件包中,已经包含了一个叫作SFTP(Secure File Transfer Protocol)的安全文件信息传输子系统,SFTP本身没有单独的守护进程,它必须使用sshd守护进程(端口号默认是22)

  • Java 添加和删除PDF图层的示例代码

    在PDF文档中,图层可以使部分内容选择性地被隐藏或显示.通过添加图层,我们可以将文本.图片.表格等元素精确定位于页面指定位置,并可将这些元素进行叠放.组合形成页面的最终效果.本文将介绍如何使用Spire.PDF for Java来添加和删除PDF图层. 使用工具: Free Spire.PDF for Java (免费版) Jar文件获取及导入: 方法1:通过官方网站 下载获取jar包.解压后将lib文件夹下的Spire.Pdf.jar文件导入Java程序.(如下图) 方法2:通过maven仓库

  • Java多线程文件分片下载实现的示例代码

    多线程下载介绍 多线程下载技术是很常见的一种下载方案,这种方式充分利用了多线程的优势,在同一时间段内通过多个线程发起下载请求,将需要下载的数据分割成多个部分,每一个线程只负责下载其中一个部分,然后将下载后的数据组装成完整的数据文件,这样便大大加快了下载效率.常见的下载器,迅雷,QQ旋风等都采用了这种技术. 分片下载 所谓分片下载就是要利用多线程的优势,将要下载的文件一块一块的分配到各个线程中去下载,这样就极大的提高了下载速度. 技术难点 并不能说是什么难点,只能说没接触过不知道罢了. 1.如何请

  • element-ui 实现响应式导航栏的示例代码

    开始之前 按照计划,前端使用Vue.js+Element UI,但在设计导航栏时,发现element没有提供传统意义上的页面顶部导航栏组件,只有一个可以用在很多需要选择tab场景的导航菜单,便决定在其基础上改造,由于我认为实现移动端良好的体验是必须的,所以便萌生了给其增加响应式功能的想法. 需求分析与拆解 假设我们的导航栏有logo和四个el-menu-item. 给window绑定监听事件,当宽度小于a时,四个链接全部放入右侧el-submenu的子菜单: 当宽度大于a时,右侧el-subme

  • JAVA用递归实现全排列算法的示例代码

    求一个n阶行列式,一个比较简单的方法就是使用全排列的方法,那么简述以下全排列算法的递归实现. 首先举一个简单的例子说明算法的原理,既然是递归,首先说明一下出口条件.以[1, 2]为例 首先展示一下主要代码(完整代码在后面),然后简述 //对数组array从索引为start到最后的元素进行全排列 public void perm(int[]array,int start) { if(start==array.length) { //出口条件 for(int i=0;i<array.length;i

随机推荐