PAT1003甲级 java

2020/7/2-2020/7/4

问题

As an emergency rescue team leader of a city, you are given a special map of your country. The map shows several scattered cities connected by some roads. Amount of rescue teams in each city and the length of each road between any pair of cities are marked on the map. When there is an emergency call to you from some other city, your job is to lead your men to the place as quickly as possible, and at the mean time, call up as many hands on the way as possible.
Input Specification:
Each input file contains one test case. For each test case, the first line contains 4 positive integers: N (≤500) - the number of cities (and the cities are numbered from 0 to N−1), M - the number of roads, C​1​​ and C​2​​ - the cities that you are currently in and that you must save, respectively. The next line contains N integers, where the i-th integer is the number of rescue teams in the i-th city. Then M lines follow, each describes a road with three integers c​1​​, c​2​​ and L, which are the pair of cities connected by a road and the length of that road, respectively. It is guaranteed that there exists at least one path from C​1​​ to C​2​​.
Output Specification:
For each test case, print in one line two numbers: the number of different shortest paths between C​1​​ and C​2​​, and the maximum amount of rescue teams you can possibly gather. All the numbers in a line must be separated by exactly one space, and there is no extra space allowed at the end of a line.
求最短路径,N个城市M条路,c1-c2的路径长度

知识点

迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径。
它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止。
指定起点s。
集合S和U。S的作用是记录已求出最短路径的顶点(以及相应的最短路径长度),而U则是记录还未求出最短路径的顶点(以及该顶点到起点s的距离)

操作步骤
(1) 初始时,S只包含起点s;U包含除s外的其他顶点,且U中顶点的距离为"起点s到该顶点的距离"[例如,U中顶点v的距离为(s,v)的长度,然后s和v不相邻,则v的距离为∞]。
(2) 从U中选出"距离最短的顶点k",并将顶点k加入到S中;同时,从U中移除顶点k。
(3) 更新U中各个顶点到起点s的距离。之所以更新U中顶点的距离,是由于上一步中确定了k是求出最短路径的顶点,从而可以利用k来更新其它顶点的距离;例如,(s,v)的距离可能大于(s,k)+(k,v)的距离。
(4) 重复步骤(2)和(3),直到遍历完所有顶点。

dijkstra java1.0

public class dijkstra {
    private int edgenum;//边
    private char[] vexs;//顶点
    private int[][] martix;//邻阶矩阵
    private static final int INF=Integer.MAX_VALUE;
    /*       vs -- 起始顶点(start vertex)。即计算"顶点vs"到其它顶点的最短路径。
     *     prev -- 前驱顶点数组。即,prev[i]的值是"顶点vs"到"顶点i"的最短路径所经历的全部顶点中,位于"顶点i"之前的那个顶点。
     *     dist -- 长度数组。即,dist[i]是"顶点vs"到"顶点i"的最短路径的长度。
     */
    public void dijkstra(int vs,int[] prev,int[] dist){
        // flag[i]=true表示"顶点vs"到"顶点i"的最短路径已成功获取
        boolean[] flag=new boolean[vexs.length];

        //初始化
        for(int i=0;i<vexs.length;i++){
            flag[i]=false;      // 顶点i的最短路径还没获取到。
            prev[i]=0;          // 顶点i的前驱顶点为0。
            dist[i]=martix[vs][i];      // 顶点i的最短路径为"顶点vs"到"顶点i"的权。distance
        }
        //自身进行初始化
        flag[vs]=true;
        dist[vs]=0;

        // 遍历mVexs.length-1次;每次找出一个顶点的最短路径。
        int k=0;
        for(int i=0;i<vexs.length;i++){
            int min=INF;
            // 寻找当前最小的路径;
            // 即,在未获取最短路径的顶点中,找到离vs最近的顶点(k)。
            for(int j=0;j<vexs.length;j++){
                if(flag[j]=false && min<dist[j]){
                    min=dist[j];
                    k=j;
                }
            }
            flag[k]=true;
            // 修正当前最短路径和前驱顶点
            // 即,当已知"顶点k的最短路径"之后,更新"未获取最短路径的顶点的最短路径和前驱顶点"。
            //相当于更新集合U,可以利用k来更新其它顶点的距离
            for(int j=0;j<vexs.length;j++){
                int tmp=(martix[k][j]==INF ? INF:(min+martix[k][j]));
                if(flag[j]==false && tmp<dist[j]){
                    dist[j]=tmp;
                    prev[j]=k;
                }
            }
        }
        // 打印dijkstra最短路径的结果
        System.out.printf("dijkstra(%c): \n", vexs[vs]);
        for (int i=0; i < vexs.length; i++)
            System.out.printf("  shortest(%c, %c)=%d\n", vexs[vs], vexs[i], dist[i]);
    }
}

:边的数量上述代码暂无使用

dijkstra java2.0

感觉没有捋顺,重新记一下


import java.util.Scanner;
//首先建立顶点类
class Vertex{
    public int vertexValue;//记录顶点的值
    public boolean isVisted;//记录该顶点是否被访问
    //初始化顶点的值和状态
    public Vertex(int vertexValue){
        this.vertexValue=vertexValue;
        this.isVisted=false;
    }
}
//其次建立图
class Graph{
    public int martix[][];
    public Vertex vertexList[];//存储顶点
    public int vertexNum;//顶点数量
    //初始化矩阵和顶点数组
    public Graph(int vertexNum){
        this.vertexNum=0;
        this.martix=new int[vertexNum][vertexNum];
        this.vertexList=new Vertex[vertexNum];
        //初始化矩阵的边,边长设置为无穷
        for(int i=0;i<vertexNum;i++){
            for(int j=0;j<vertexNum;j++){
                if(i==j){
                    martix[i][j]=0;
                }else {
                    martix[i][j]=Integer.MAX_VALUE;
                }
            }
        }
    }
    //添加顶点的值
    public void addVertex(int value){
        vertexList[vertexNum++]=new Vertex(value);
    }
    //添加边
    public void addEdge(int start,int end,int value){
        martix[start][end]=value;
        martix[end][start]=value;
    }
}
public class Main {
    private static int MAX_VALUE=505;
    private static int INF=Integer.MAX_VALUE;
    private static int[] dist=new int[MAX_VALUE];//记录最终最短路径
    private static int[] num=new int[MAX_VALUE];//记录计算时不同的最短路径条数
    private static int[] sum=new int[MAX_VALUE];//记录救援队总数,即顶点值得和

    public static void main(String[] args){
        Scanner sc=new Scanner(System.in);
        int N=sc.nextInt();//n个城市
        int M=sc.nextInt();//m条路,几乎没有作用
        int C1=sc.nextInt();//起点城市
        int C2=sc.nextInt();//终点城市
        Graph city=new Graph(N);

        //添加城市
        for(int i=0;i<N;i++){
            city.addVertex(sc.nextInt());//添加城市得救援队
        }
        //添加边
        for(int i=0;i<M;i++){
            city.addEdge(sc.nextInt(),sc.nextInt(),sc.nextInt());
        }
        //计算距离C1得最短路径
        dist[C1]=0;
        num[C1]=1;
        sum[C1]=city.vertexList[C1].vertexValue;
        //初始化dist和sum
        for(int i=0;i<N;i++){
            dist[i]=city.martix[C1][i];
            sum[i]=city.vertexList[i].vertexValue;
        }
        //对图中除了C1得点进行遍历
        for(int i=(C1+1)%N;i!=C1;i=(i+1)%N){
            int index=-1;//记录最短路径的另一个点
            int mindist=INF;
            for(int j=0;j<N;j++){
                if(!city.vertexList[j].isVisted && dist[j]<mindist){
                    mindist=dist[j];
                    index=j;
                }
            }
            //没有最短路径,结束循环
            if(index==-1) {
                break;
            }
            //设置确定的顶点状态
            city.vertexList[index].isVisted=true;
            //利用index更新路径
            for(int j=0;j<N;j++){
                if(!city.vertexList[j].isVisted && city.martix[index][j]!=INF){
                    if(dist[j]>dist[index]+city.martix[index][j]){
                        dist[j]=dist[index]+city.martix[index][j];
                        num[j]=num[index];
                        sum[j]=sum[index]+city.vertexList[j].vertexValue;
                    }else if(dist[j]==dist[index]+city.martix[index][j]){
                        num[j]=num[index]+num[j];
                        if(sum[index]+city.vertexList[j].vertexValue>sum[j]){
                            sum[j]=sum[index]+city.vertexList[j].vertexValue;
                        }
                    }
                }
            }
        }
        System.out.println(num[C2]+" "+sum[C2]);
    }
}

代码详情请参考
https://blog.csdn.net/hihiztc/article/details/101195873?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值