广度优先搜索BFS解决路径最短问题

拿出一道第十二届蓝桥杯JavaB组省赛的E题来实现代码

试题 E: 路径
本题总分:10 分

【问题描述】
小蓝学习了最短路径之后特别高兴,他定义了一个特别的图,希望找到图
中的最短路径。
小蓝的图由 2021 个结点组成,依次编号 1 至 2021。
对于两个不同的结点 a, b,如果 a 和 b 的差的绝对值大于 21,则两个结点
之间没有边相连;如果 a 和 b 的差的绝对值小于等于 21,则两个点之间有一条
长度为 a 和 b 的最小公倍数的无向边相连。
例如:结点 1 和结点 23 之间没有边相连;结点 3 和结点 24 之间有一条无
向边,长度为 24;结点 15 和结点 25 之间有一条无向边,长度为 75。
请计算,结点 1 和结点 2021 之间的最短路径长度是多少。
提示:建议使用计算机编程解决问题。

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

public class Graph {
    public static void main(String[] args) {
        List<Vertex> list = new ArrayList<>();
        for (int i = 1; i < 2022; i++) {
            list.add(new Vertex(i));
        }
        for (int i = 0; i < list.size(); i++) {
            for (int j = 0; j < list.size(); j++) {
                if(Math.abs(i-j)<=21 && i != j){
                    int lcm = lcm(list.get(i).value,list.get(j).value);
                    list.get(i).edges.add(new Edge(lcm,list.get(j)));
                }
            }
        }
        dfs(list.get(0));
        System.out.println(list.get(2020).dist);
    }
    //求最大公约数
    public static int gcd(int a,int b){
        if(b == 0){
            return a;
        }
        return gcd(b,a%b);
    }
    //求最小公倍数
    public static int lcm(int a,int b){
        return a * b / gcd(a,b);
    }
    //dfs深度优先搜索遍历
    public static void dfs(Vertex vertex){
        Queue<Vertex> queue = new LinkedList<>();
        vertex.dist = 0;
        //每个节点只遍历一次它的边
        vertex.isVisit = true;
        queue.offer(vertex);
        while (!queue.isEmpty()){
            //获取队列第一个元素,并遍历它的边
            Vertex poll = queue.poll();
            for (Edge edge : poll.edges) {
                int dist = poll.dist + edge.weight;
                //从poll节点各个边到达的其它节点,如果距离更短了就更新
                if(dist < edge.linked.dist){
                    edge.linked.dist = dist;
                }
                //判断节点的关联边是否遍历过,没有就进队列
                if(!edge.linked.isVisit){
                    queue.offer(edge.linked);
                    edge.linked.isVisit = true;
                }
            }
        }
    }
}
//节点类
class Vertex{
    int value;
    List<Edge> edges = new ArrayList<>();
    int dist = Integer.MAX_VALUE;
    Boolean isVisit = false;

    public Vertex(int value) {
        this.value = value;
    }
}
//边类
class Edge{
    int weight;
    Vertex linked;

    public Edge(int weight, Vertex linked) {
        this.weight = weight;
        this.linked = linked;
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值