/*
*
* 时间最短的基础上,花费最少
* */
package cn.java.mhz;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
/**
* dfs search
* @author MHZ
*
*/
class DfsSearch{
static final int maxv = 100+5;
static final int INF = 0x3f3f3f3f;
static final double INF1 = 1000000000.0;
public Integer path[][];
public boolean done[];
public Integer parent[];
public int solve;
public double solvecost;
public Integer path1[][];
public Integer parent1[];
public boolean flag;
//构造方法
DfsSearch(){
this.flag=false;
this.solve = INF;
this.solvecost =INF1;
this.path1=new Integer[maxv][];
this.parent1=new Integer[maxv];
this.path =new Integer[maxv][];
for(int i = 0;i<maxv;i++)
{
path[i] = new Integer[maxv];
for(int j=0;j<maxv;j++)
path[i][j] = 0;
}
for(int i = 0;i<maxv;i++)
{
path1[i] = new Integer[maxv];
for(int j=0;j<maxv;j++)
path1[i][j] = 0;
}
this.parent =new Integer[maxv];
this.done=new boolean[maxv];
for(int i=1;i<maxv;i++)
done[i]=false;
for(int i = 0;i<maxv;i++)
{
parent[i] = 0;
}
for(int i = 0; i<maxv;i++)
{
parent1[i] = 0;
}
}
//成员方法
//相对于dfs,类中的其它均为全局变量
public void dfs(Edge[][] G, int head,int end,int st,int en,int v,int pos,int sum,double sumcost)
{
if(sum > solve||(sum==solve&&sumcost>solvecost)) {
return;
}
if(pos == end) {
flag = true;
if(solve>=sum) {
if(solve>sum) {
solve=sum;
solvecost = sumcost;
int last = end,cnt=0;
while(last!=head)
{
parent1[cnt++] = last;
last = parent[last];
}
parent1[cnt++] = head;
for(int i=cnt-1;i-1>=0;i--)
path1[parent1[i]][parent1[i-1]] = path[parent1[i]][parent1[i-1]];
}
else if(solve==sum) {
if(solvecost > sumcost) {
solvecost = sumcost;
int last = end,cnt=0;
while(last!=head)
{
parent1[cnt++] = last;
last = parent[last];
}
parent1[cnt++] = head;
for(int i=cnt-1;i-1>=0;i--)
path1[parent1[i]][parent1[i-1]] = path[parent1[i]][parent1[i-1]];
}
}
}
return;
}
for(int i=1;i<=v;i++)
{
if(done[i]||G[pos][i].trans==null) {
continue;
}
for(int j=0;j<G[pos][i].trans.size();j++)
{
if(pos==head) {
if(G[pos][i].starttime.get(j)>=st&&G[pos][i].starttime.get(j)<=en) {
parent[i] = pos;
path[pos][i] = j;
done[i] = true;
dfs(G, head, end, st, G[pos][i].starttime.get(j)+G[pos][i].pasttime.get(j), v,i ,sum+G[pos][i].pasttime.get(j),sumcost+G[pos][i].cost.get(j));
done[i] = false;
}
}
else {
//System.out.println(pos+" "+en +" "+ i +" "+G[pos][i].starttime.get(j));
if(G[pos][i].starttime.get(j)>=en)
{
parent[i] = pos;
path[pos][i] = j;
done[i] = true;
dfs(G, head, end, st, G[pos][i].starttime.get(j)+G[pos][i].pasttime.get(j), v, i ,sum+G[pos][i].pasttime.get(j)+G[pos][i].starttime.get(j)-en,sumcost+G[pos][i].cost.get(j));
done[i] =false;
}
}
}
}
done[pos]=false;
return;
}
}
class Edge{
public ArrayList<Integer> starttime;
public ArrayList<Integer> endtime;
public ArrayList<Double> cost;
public ArrayList<Integer> pasttime;
public ArrayList<String> trans;
public Edge()
{
this.starttime = new ArrayList <Integer> ();
this.endtime = new ArrayList<Integer> ();
this.cost = new ArrayList<Double> ();
this.pasttime = new ArrayList<Integer> ();
this.trans = new ArrayList<String> ();
}
//构造器
public Edge(ArrayList<Integer> starttime, ArrayList<Integer> endtime, ArrayList<Double> cost,
ArrayList<Integer> pasttime, ArrayList<String> trans) {
super();
this.starttime = starttime;
this.endtime = endtime;
this.cost = cost;
this.pasttime = pasttime;
this.trans = trans;
}
}
public class MySearchClass {
static final int maxv = 100+5;
public static int time(String s)
{
int hour,minute;
hour = (s.charAt(0)-'0')*10+(s.charAt(1)-'0');
minute = (s.charAt(3)-'0')*10+(s.charAt(4)-'0');
return hour*3600+minute*60;
}
//传入整张图,头结点,尾节点,可接受时间范围
//寻找一条时间最短的途径
public static void main(String[] args)
{
System.out.println("请输入点数和边数:");
Integer v,e;
Scanner sc = new Scanner(System.in);
String str = new String();
str = sc.nextLine();
String[] str1 = str.trim().split(" ");
v = Integer.parseInt(str1[0]);
e = Integer.parseInt(str1[1]);
System.out.println("请输入可接受出发时间区间:");
String s = new String();
s = sc.nextLine();
str1 = s.trim().split(" ");
//得到可接受时间区间
Integer st = Integer.valueOf(time(str1[0]));
Integer en = Integer.valueOf(time(str1[1]));
//得到起始和终点
System.out.println("请输入起始点和终点:");
String s1 = new String();
s1 = sc.nextLine();
str1 = s1.trim().split(" ");
Map<String,Integer> map1 = new HashMap<>();
Map<Integer,String> map2 = new HashMap<>();
map1.clear();
map2.clear();
int pos=1;
System.out.println("请输入 边的信息:");
Edge[][] G = new Edge[maxv][];
for(int i=0;i<maxv;i++)
{
G[i] = new Edge[maxv];
for(int j=0;j<maxv;j++)
{
G[i][j]=new Edge();
}
}
//存放整个图结构
for(int i=0;i<e;i++)
{
String s2=sc.nextLine();
String[] str11 = s2.trim().split(" ");
int v1,v2;
if(map1.containsKey(str11[0])) {
v1 = map1.get(str11[0]);
}
else {
v1 = pos;
map1.put(str11[0], pos);
map2.put(pos, str11[0]);
pos++;
}
if(map1.containsKey(str11[1]))
{
v2 = map1.get(str11[1]);
}
else {
v2 = pos;
map1.put(str11[1],pos);
map2.put(pos, str11[1]);
pos++;
}
//有向图
G[v1][v2].trans.add((String)str11[2]);
G[v1][v2].starttime.add(time(str11[3]));
G[v1][v2].endtime.add(time(str11[4]));
G[v1][v2].cost.add(Double.parseDouble(str11[5]));
G[v1][v2].pasttime.add(Integer.parseInt(str11[6]));
// System.out.printf("%d %d\n",v1,v2);
}
DfsSearch Ms = new DfsSearch();
int head = map1.get(str1[0]);
int end = map1.get(str1[1]);
Ms.done[head]=true;
Ms.flag=false;
Ms.dfs(G, head, end, st, en, v, head, 0,0.0);
if(Ms.flag==true)
{
Integer []parent = Ms.parent1;
Integer [][]path = Ms.path1;
List <Integer> L = new ArrayList<>();
for(int i=0;i<parent.length;i++)
if(parent[i].equals(head)) break;
else {
L.add(parent[i]);
}
L.add(head);
//数组翻转
int len = L.size();
for(int i=0;i<len/2;i++)
{
parent[i] = parent[len-1-i] + parent[i];
parent[len-1-i] = parent[i] - parent[len-1-i];
parent[i] = parent[i] - parent[len-1-i];
}
StringBuilder sb =new StringBuilder();
System.out.printf("由%s到达%s花费时间最短的基础上,金钱花费最少的乘坐方式为:\n",str1[0],str1[1]);
sb.append(" ");
for(int i=0;i<len-1;i++)
{
if(i==0) {
sb.append(map2.get(parent[i])+"--"+G[parent[i]][parent[i+1]].trans.get(path[parent[i]][parent[i+1]])+"--"+map2.get(parent[i+1]));
}
else {
sb.append("--"+G[parent[i]][parent[i+1]].trans.get(path[parent[i]][parent[i+1]])+"--"+map2.get(parent[i+1]));
}
if(i==len-2) {
break;
}
}
System.out.println(sb.toString());
//System.out.println(Ms.solve);
//System.out.println(Ms.solvecost);
}else {
System.out.println("在指定的时间区间内未查询到可出行的路径!!!!");
}
}
}
几点经验总结:
1.java中为了安全与封装,避免使用全局变量,但是有时候需要使用全局变量,这种时候可以另外定义一个类,把所要使用的方法定义为类的成员方法,这样相对于类的成员方法,类的成员变量便成为了这个类的全局变量,再实例化类的对象,通过类的对象来调用此方法即可
2.写这个代码的时候,经常遇到空指针的问题,后来才发现是由于二维数组在初始化的时候,要对二维数组中的每一个元素都进行初始化,而不是仅仅对于整个数组进行初始化