Algorithm Practice for 1582

Which Way Do I Go?
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 394 Accepted: 66

Description

You've decided that the time is right for the next Internet map startup. Your inspiration for this venture is your directionally impaired spouse, who doesn't care for the shortest or quickest routes generated by current online map systems-instead, easier is better. 
The backbone of your operation is, of course, your algorithm for calculating directions. Your algorithm must accept the map from your massive database of the entire country and produce the best route that meets the customer's query. Queries consist of an origin, destination, and the optimization goal, which can be for the shortest route, fastest route, or route with the fewest turns. You are guaranteed that there will be a path between source and destination for any query asked. 

Input

There are three sections in the input file, the first lists the cities, the second lists the roads, and the third lists the queries. 
The first line of input is the number of cities, c, followed by c lines each containing the name of a city. There is no whitespace in a city name. 
The next line is the number of roads, r, followed by r lines describing a road. Each road description has the following form: 
< RoadName > < CityA > < ABDistance > < ABTime > < CityB > [< BCDist > < BCTime > < CityC > [...]] 
There is no whitespace in a road's name. Roads may pass through any number of cities. The cities appear in the order the road passes through them. No road passes through the same city multiple times. Roads are bidirectional. The distance and time (both real numbers) it takes to follow a road between each pair of cities is the distance and time listed between those two names.When following a road between multiple cities (A to C, for example), the distance and time is cumulative for all steps along the path. 
The remainder of the lines in the file each list one query. Queries are of the form: 
< querytype > < origin > < destination > 
Querytype is one of time, distance, or turns and the origin and destination are the names of cities. 
The queries end at end-of-file.

Output

For each query, your output will begin with a line: 
from < origin > 
Each following line will be of the form: 
< roadName > to < cityname > 
which lists the road to turn onto from the previous city, and the city to take that road to. If a single road is followed between multiple cities, only the final city reached on that road before turning onto another road is listed. The final city listed will be the destination city. 

Sample Input

5
Chicago
DesMoines
OklahomaCity
Dallas
LosAngeles
4
I80 Chicago 300 4 DesMoines
I35 DesMoines 550 7.3 OklahomaCity 205 3 Dallas
I40 OklahomaCity 1330 20.5 LosAngeles
Rt66 Chicago 2448 46 LosAngeles
time Chicago LosAngeles
turns Chicago LosAngeles

Sample Output

from Chicago
I80 to DesMoines
I35 to OklahomaCity
I40 to LosAngeles
from Chicago
Rt66 to LosAngeles

Solution:

package id1582;

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

public class WhichWayDoIGo {
	BufferedReader in = null;
	String[] cities = null;
	Graph graph = null;
	final boolean DEBUG = false;

	int cityNum = 0;
	int routesNum = 0;
	public WhichWayDoIGo() {
		in = new BufferedReader(new InputStreamReader(System.in));
	}
	private void start() throws NumberFormatException, IOException{
		String str = null;
		String[] strArry = null;
		LinkedList<Edge> solution = null;
		Graph duplicate_graph = null;
		cityNum = Integer.parseInt(in.readLine());
		cities = new String[cityNum];
		for(int i = 0; i < cityNum; i++)
			cities[i] = in.readLine();
		routesNum = Integer.parseInt(in.readLine());
		graph = new Graph(routesNum);
		for(int i = 0; i < routesNum; i++){
			graph.addNode(in.readLine());
		}
		if(DEBUG) graph.printGraph();
		str = in.readLine();
		while(!str.equals("") || str != null){
			duplicate_graph = new Graph(graph);
			strArry = str.split(" ");
			solution = search4solution(strArry[0],strArry[1],strArry[2],duplicate_graph);
			printSolution(solution);
			str = in.readLine();
			solution.clear();
		}
	}
	private void printSolution(LinkedList<Edge> solution){
		Edge edge = null;
		if(solution == null){
			System.out.println("Solution is null");
			System.exit(0);
		}
		else
			edge = solution.poll();
			System.out.println("from " + edge.srcName);
			System.out.println(edge.routeName + " to " + edge.targetName);
			while(!solution.isEmpty()){
				edge = solution.poll();
				if(edge != null) System.out.println(edge.routeName + " to " + edge.targetName);
			}
	}
	private LinkedList<Edge> search4solution(String format, String orig, String dest, Graph graph){
		EdgeList originEdgelist = null;
		LinkedList<Edge> bestSolution = null;
		LinkedList<LinkedList<Edge>> paths = null;
		for(int i =0; i < graph.adjList.size(); i++)
			if(graph.adjList.get(i).OriginName.equals(orig)){
				originEdgelist = graph.adjList.remove(i);
				break;
			}
		if(originEdgelist == null)
			System.out.println("Can not find this originCity");
		
		paths = getAvailablePaths(originEdgelist,orig,dest,graph);
		bestSolution = findBestSolution(paths,format);
		if (bestSolution.isEmpty()) {
				System.out.println("bestSolution is empty");
				System.exit(0);
		}
		return bestSolution;
	}
	
	
	private LinkedList<Edge> findBestSolution(LinkedList<LinkedList<Edge>> listSolution, String format){
		int cheapestPathIndex = Integer.MAX_VALUE;
		float cheapstCost = Float.MAX_VALUE;
		float cost = 0;
		for(int i = 0; i < listSolution.size(); i++){
			if(DEBUG)
				System.out.println("Get in another path");
			if(DEBUG){
				for(int j = 0; j < listSolution.get(i).size(); j++){
					if(listSolution.get(i).get(j) != null){
						listSolution.get(i).get(j).print();
						System.out.println("");
					} else
						System.out.println("Edge is null");
				}
			}
			if(format.equals("time"))
				cost = calculateTimeCost(listSolution.get(i),0);
			else if(format.equals("turns"))
				cost = calculateTurnsCost(listSolution.get(i),0);
			else if(format.equals("distance"))
				cost = calculateDistanceCost(listSolution.get(i),0);

			if(cost < cheapstCost) {
				if(DEBUG)
					System.out.println("Less than the cheapstCost index changed to " + i);
				cheapstCost = cost;
				cheapestPathIndex = i;
			}
		}	
		
		if(DEBUG)
			System.out.println("\nThis path cost is " + cheapstCost);
		return listSolution.get(cheapestPathIndex);
	}
	private float calculateDistanceCost(LinkedList<Edge> path, int index){
		Edge edge = null;
		if(index < path.size()){
			edge = path.get(index);
			if(edge == null) {
				System.out.println("Edge is null at calculateDistanceCost function");
				return calculateDistanceCost(path, index + 1);
			}
			return (edge.distance + calculateDistanceCost(path, index + 1));
		} else
			return 0;
	}
	private float calculateTurnsCost(LinkedList<Edge> path, int index){
		Edge edge = null;
		if(index < path.size()){
			edge = path.get(index);
			if(edge == null) return calculateTurnsCost(path, index + 1);
			return (1 + calculateTurnsCost(path, index + 1));
		} else
			return 0;
	}
	private float calculateTimeCost(LinkedList<Edge> path, int index){
		Edge edge = null;
		if(index < path.size()){
			edge = path.get(index);
			if(edge == null) return calculateTimeCost(path, index + 1);
			return (edge.timeCost + calculateTimeCost(path, index + 1));
		} else
			return 0;
	}
	
	private LinkedList<LinkedList<Edge>> getAvailablePaths(EdgeList origEdgelist,
			String orig,String dest,Graph graph){

		//	System.out.println("Go in TimeOptimized Function");
		Solution solution = new Solution();
		// put origin city name to path
		solution.parentSolution = null;
		Solution subSolutions = null;
		LinkedList<Solution> listSolutions = new LinkedList<Solution>();
		// distribute each edge connectted with origin to helper function
		for(int i = 0; i < origEdgelist.edgeList.size(); i++){
			subSolutions = searchPathWithTimeOptimized_helper(origEdgelist.edgeList.get(i),dest,graph);
			// if exists a path from this edge to destination, then subSolutions is not null
			if(subSolutions != null){
				listSolutions.offer(subSolutions);
			}
		}
		if (listSolutions.isEmpty()) {
			System.out.println("listSolutions is empty");
			System.exit(0);
		}
		// put all sub paths to path 
		solution.subSolutions = listSolutions;
		return getAvaiblPaths(solution);
	}
	private LinkedList<LinkedList<Edge>> getAvaiblPaths(Solution solutions){
		LinkedList<Edge> listEdge = new LinkedList<Edge>();
		@SuppressWarnings("unchecked")
		Edge parentEdge = solutions.parentSolution;
		LinkedList<Solution> subSolutions = solutions.subSolutions;
		LinkedList<LinkedList<Edge>> listSolution = new LinkedList<LinkedList<Edge>>();
		while(!subSolutions.isEmpty())
	    	getAvaiblPaths_helper(parentEdge,listEdge,subSolutions.poll(),listSolution);
		return listSolution;
	}
	
	// parentEdge is parennt Edge, parent_listEdge records the path till now, solution is current node, listSolution cllect all the parent_listEdge at last 
	private void getAvaiblPaths_helper(Edge parentEdge,LinkedList<Edge> parent_listEdge,Solution solution, LinkedList<LinkedList<Edge>> listSolution){
		@SuppressWarnings("unchecked")
		LinkedList<Edge> listEdge = (LinkedList<Edge>) parent_listEdge.clone();
		if(parentEdge != null) 
			listEdge.offer(parentEdge);
		Edge edge = solution.parentSolution;
		LinkedList<Solution> subSolutions = solution.subSolutions;
		if(subSolutions == null){
			if(edge != null)
				listEdge.offer(edge);
			listSolution.offer(listEdge);
			return;
		}
		while(!subSolutions.isEmpty()){
			getAvaiblPaths_helper(edge,listEdge,subSolutions.poll(),listSolution);
		}
	}

	
	private Solution searchPathWithTimeOptimized_helper(Edge edge, String dest, Graph graph ){
		EdgeList originEdgelist = null;
		Solution solutionHelper = null;
		Solution solutions = new Solution();
		LinkedList<Solution> listSubSolutions = new LinkedList<Solution>();
		String src = edge.targetName;
		solutions.parentSolution = edge;
		
	//	System.out.println("Get in searchPathWithTimeOptimized_helper");
	//	edge.print();
	//	System.out.println("");
		
		
		if(src.equals(dest)){
			 return solutions;
		}
		Edge subEdge = null;
		for(int i = 0; i < graph.adjList.size(); i++)
			if(graph.adjList.get(i).OriginName.equals(src)){
				if(DEBUG) System.out.println("Found city " + src + "," + src + "'s edgeList was removed ");
				originEdgelist = graph.adjList.remove(i);
				break;
			}
		if(originEdgelist == null) {
			return null;
		}
		while(!originEdgelist.edgeList.isEmpty()){
			subEdge = originEdgelist.edgeList.poll();
			solutionHelper = searchPathWithTimeOptimized_helper(subEdge,dest,graph);
			if(solutionHelper != null){
				listSubSolutions.offer(solutionHelper);
			}
		}
		if(listSubSolutions.isEmpty()) return null;
		else {
			solutions.subSolutions = listSubSolutions;
			return solutions;
		}
	}
	
	public static void main(String[] args){
		try {
			new WhichWayDoIGo().start();
		} catch (NumberFormatException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	private class Graph{
		int nodeNum = 0;
		LinkedList<EdgeList> adjList = null;
		public Graph(int nodeNum){
			this.nodeNum = nodeNum;
			this.adjList = new LinkedList<EdgeList>();
		}
		public Graph(Graph graph){
			this.nodeNum = graph.nodeNum;
			this.adjList = new LinkedList<EdgeList>();
			for(int i =0; i < graph.adjList.size(); i++)
				this.adjList.offer(new EdgeList(graph.adjList.get(i)));
		}
		public void printGraph(){
			for(int i = 0; i < this.adjList.size(); i++)
				this.adjList.get(i).print();
		}
		private void addNode(String str){
			EdgeList edgelist = null;
			String[] strArry = str.split(" ");
			int nodesNum = (strArry.length - 2) / 3 + 1;
			for(int i = 0; i < nodesNum; i++){
				if(hasThisOriginName(strArry[i * 3 + 1],adjList)) {
					edgelist = popThisEdgeList(strArry[i * 3 + 1],adjList);
					adjList.offer(addnewedges(i * 3 + 1,nodesNum,strArry,edgelist));
				}else{
					EdgeList edgelist1 = new EdgeList(strArry[i * 3 + 1]);
					edgelist1 = addnewedges(i * 3 + 1,nodesNum,strArry,edgelist1);
					adjList.offer(edgelist1);
				}
			}
		}
		private EdgeList addnewedges(int origIndex,int nodesNum, String[] strArry, EdgeList edgelist){
			
			if(origIndex == strArry.length - 1){
				try{
					edgelist = addEdge(strArry[0],strArry[origIndex],strArry[origIndex - 2],strArry[origIndex - 1],strArry[origIndex - 3],edgelist);
				}catch(Exception e){
					System.err.println("err here " + e.getMessage());
					System.exit(0);
				}
			}
			else if(origIndex != 1){
				edgelist = addEdge(strArry[0],strArry[origIndex],strArry[origIndex + 1],strArry[origIndex + 2],strArry[origIndex + 3],edgelist);
				edgelist = addEdge(strArry[0],strArry[origIndex],strArry[origIndex - 2],strArry[origIndex - 1],strArry[origIndex - 3],edgelist);
			}else{
				edgelist = addEdge(strArry[0],strArry[origIndex],strArry[origIndex + 1],strArry[origIndex + 2],strArry[origIndex + 3],edgelist);
			}
			return edgelist;
		}
		
		private EdgeList addEdge(String routeName,String srcName,String distStr, String timeStr, String Destination, EdgeList edgelist){
			Edge edge = new Edge(routeName,srcName,distStr,timeStr,Destination);
			
			edgelist.edgeList.offer(edge);
			 return edgelist;
		}
		// return the EdgeList whose originName is originName;
		private EdgeList popThisEdgeList(String originName, LinkedList<EdgeList>  adjList){
			EdgeList edglist = null;
			for(int i = 0; i < adjList.size(); i++){
				if(adjList.get(i).OriginName.equals(originName))
					return adjList.remove(i);
			}
			return edglist;
		}
		// returns true if origName exists in the adjList
		private boolean hasThisOriginName(String origName,LinkedList<EdgeList> adjList){
			for(int i = 0; i < adjList.size(); i++){
				if(origName.equals(adjList.get(i).OriginName))
					return true;
			}
			return false;
		}
	}
	private class Solution {
		Edge parentSolution = null;
		LinkedList<Solution> subSolutions = null;
		
		public Solution(Edge parentSolution, LinkedList<Solution> subSolutions){
			this.parentSolution = parentSolution;
			this.subSolutions = subSolutions;
		}
		public Solution(Edge parentSolution){
			this.parentSolution = parentSolution;
		}
		public Solution(LinkedList<Solution> subSolutions){
			this.subSolutions = subSolutions;
		}
		public Solution(){
			
		}
	}
	private class EdgeList{
		LinkedList<Edge> edgeList = null;
		String OriginName = null;
		public EdgeList(String OriginName){
			this.OriginName = OriginName;
			edgeList = new LinkedList<Edge>();
		}
		public EdgeList(EdgeList edgelist){
			this.OriginName= edgelist.OriginName;
			this.edgeList = new LinkedList<Edge>();
			for(int i = 0; i < edgelist.edgeList.size(); i++)
				this.edgeList.offer(new Edge(edgelist.edgeList.get(i)));
		}
		public void print(){
			System.out.print("adjList: From: " + this.OriginName + "  To: ");
			for(int j = 0; j < this.edgeList.size(); j++){
				this.edgeList.get(j).print();
				System.out.print(",   ");
			}
			System.out.println("");
		}
	}
	private class Edge{
		String targetName = null;
		String srcName = null;
		String routeName = null;
		int distance = 0;
		float timeCost = 0;
		public Edge(Edge edge){
			this.targetName = edge.targetName;
			this.srcName = edge.srcName;
			this.routeName = edge.routeName;
			this.distance = edge.distance;
			this.timeCost = edge.timeCost;
		}
		/*public Edge(String srcName, String targetName){
			this.srcName = srcName;
			this.targetName = targetName;
			this.routeName = "No Name";
		}*/
		public Edge(String routeName,String srcName,String distanceStr, String timeStr, String targetName){
		try{
			this.routeName = routeName;
			this.srcName = srcName;
			this.distance = Integer.parseInt(distanceStr);
			this.timeCost = Float.parseFloat(timeStr);
			this.targetName = targetName;
		} catch (Exception e){
			System.err.println("new Edge: " + routeName + "	" + distanceStr + "		" + timeStr + "		" + targetName + '\n' + e.getMessage());
			System.exit(0);
		}
		}
		public void print(){
			System.out.print("  " + srcName + " 	" + targetName);
		}
	}
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值