您的位置:首页 > 其它

PAT甲级1003---迷宫问题(DFS或Dijkstra)

2017-10-09 18:14 369 查看
题目链接:https://www.patest.cn/contests/pat-a-practise/1003

题目大意:给定起点和终点,找到所有最短所有路径,打印最短路径数目和最短路径下的最大点权和。

从九月开始刷PAT,乙级刷的差不多后到甲级,乙级大多是数组和字符串处理,这道题是自己做的第一道进阶算法题。上个学期离散课上学过Dijkstra,但是只碰到过单条最短路径的情况,于是一开始就没有考虑到多条。后来自己把图画了出来才发现示例给出的数据是有两条的,再读题发现要输出所有最短路径的条数。

一开始的做法是先用Dijkstra让每个顶点维护一个前驱顶点数组,最后再用BFS或DFS遍历路径,后来发现这样做时间复杂度太高。于是上网搜,发现两种思路:

1,用DFS遍历起点和终点间的每一条路径,在遍历过程中在递归参数中保存各条路线的长度与点权和,遍历到终点时判断是否为最短路径:小于当前最短路径则置为将最短路径数1,等于则加1),然后剪枝。

第一次知道用DFS也可以求最短路径,后来发现这种起点和终点确定的问题叫做迷宫问题,不用Dijkstra或Floyd也是可以做的,因为只要遍历到终点时再判断边权和就可以了。

代码:http://blog.csdn.net/iaccepted/article/details/21451949

2,用Dijkstra遍历,每个点用数组保存当前路径最大点权和与当前最短路径数,更新路线时更新这两个数组。最大点权和等于父节点的最大点权和加上当前点的点权,最短路径数的处理方法和上面类似:小于当前最短路径则等于父节点的最短路径数,等于当前最短路径则加上父节点的最短路径数。

代码:https://www.liuchuo.net/archives/2359

自己做的时候是用第二种方法,时间复杂度为Dijkstra算法的时间复杂度,即O(n²)(未使用邻接表和堆优化)。处理了非连通情况和一个小bug,第三次提交ac。代码如下:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;

public class Main{
public static void main(String[] args) throws IOException {
BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));
String[] info=reader.readLine().split("\\s");
int cities=Integer.parseInt(info[0]);
int roadsAmount=Integer.parseInt(info[1]);
int current=Integer.parseInt(info[2]);
int save=Integer.parseInt(info[3]);
String[] info2=reader.readLine().split("\\s");
int[] teams=new int[info2.length];
for (int i = 0; i < info2.length; i++) {
teams[i]=Integer.parseInt(info2[i]);
}
int[][] roads=new int[cities][cities];
for (int i = 0; i < roadsAmount; i++) {
String[] road=reader.readLine().split("\\s");
roads[Integer.parseInt(road[0])][Integer.parseInt(road[1])]=Integer.parseInt(road[2]);
roads[Integer.parseInt(road[1])][Integer.parseInt(road[0])]=Integer.parseInt(road[2]);
}
int[] sPath=new int[cities];
int[] paths=new int[cities];
int[] maxTeams=new int[cities];
paths[current]=1;
maxTeams[current]=teams[current];
ArrayList<Integer> shortest=new ArrayList<>();
shortest.add(current);
int start=current;
boolean next=true;
while (next) {
for (int i = 0; i < cities; i++) {
if (i==start||shortest.contains(i)||roads[current][i]==0) {
continue;
}
if (sPath[i]==0||sPath[i]>roads[current][i]+sPath[current]) {
sPath[i]=roads[current][i]+sPath[current];
paths[i]=paths[current];
maxTeams[i]=maxTeams[current]+teams[i];
}else if (sPath[i]==0||sPath[i]==roads[current][i]+sPath[current]) {
paths[i]+=paths[current];
if (maxTeams[current]+teams[i]>maxTeams[i]) {
maxTeams[i]=maxTeams[current]+teams[i];
}
}
}
int min=Integer.MAX_VALUE;
for (int i = 0; i < sPath.length; i++) {
if (sPath[i]!=0&&!shortest.contains(i)&&sPath[i]<min) {
min=sPath[i];
current=i;
}else if (i==sPath.length-1&&min==Integer.MAX_VALUE) {
next=false;
}
}
shortest.add(current);
}
System.out.print(paths[save]+" "+maxTeams[save]);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: