其他分享
首页 > 其他分享> > 出行 - Travel - Dijkstra

出行 - Travel - Dijkstra

作者:互联网

出行

时间限制:最多X个用例,2秒(C/C++),2.5秒(Java)

 

当前有一个N行M列网格模型的国家。每个单元格代表着一座城市。每次通过一座城市时,都会产生一笔通行费。

今年夏天将在这个国家的某座城市举办一个盛大的庆典活动。约翰和克洛伊为了参加这个庆典,他们需要各自从自己居住的城市出发,前往到举办庆典活动的城市。前往时,可以移动到上下左右相邻的城市,一旦离开一座城市,就需要立即支付通行费。此外,由于通行费是按团体收费而不是按人数收费,因此在移动的途中,在某一座城市碰面,然后一同出行要比单独出行花费的更少。

 <图 1>                                                      <图 2> 

如上图所示,假设约翰居住在[2,2],克洛伊居住在[2,5],举办庆典的城市位于 [5,4]。(这时,坐标中第一个数字表示行数,第二个数字表示列数,并且每个单元格中的数字表示通行费。)约翰前往举办庆典城市的最低费用路径为<图1>的蓝色路径,该费用为18,克洛伊的情况,最低费用路径为绿色路径,该费用为15。如果按照<图2>一样,约翰和克洛伊在[2,4]上碰面,然后一起移动时,费用会变为10 + 3 + (4 + 9 + 1) = 27,这时的费用为最低。

※ 举办庆典活动的城市不收取通行费;约翰和克洛伊共同经过的城市,可以一起支付通行费。

帮助约翰和克洛伊求出俩人移动到举办庆典的城市时,所需要的最低费用。

 

[限制条件]

1.网格的行数N和列数M为介于3到500之间的整数。(3 <= N, M <= 500)

2.各城市的通行费C为介于0到10,000之间的整数。(0 <= C <= 10,000)

3.即使经过的是曾经到过的城市,但仍然需要再次支付通行费。

4.如果俩人一起同行,那么仅收取一次的通行费。

5.举办庆典活动的城市不收取通行费。如果他们在出发城市碰面,然后一起同行,那么会收取通行费,但仅需支付一人的费用。

6.约翰居住的城市、克洛伊居住的城市以及举办庆典活动的城市为三座不同的城市。

 

[输入]

第一行给出测试用例数量T,接着给出T种测试用例。第一行空格区分给出网格的行数N和列数 M、约翰出发城市的行数R1和列数C1、克鲁伊出发城市的行数R2和列数C2以及举办庆典活动的行数R3和列数C3。接下来通过N行,每行空格区分给出M个城市的通行费(C)。

 

[输出]

一个测试用例输出一行。每个测试用例都输出“#x”(其中x表示测试用例编号,从1开始),加一个空格后,输出约翰和克洛伊前往举办庆典活动的城市时,所需要的最低费用。

 

[输入输出 示例]

(输入)

3
5 6 2 2 2 5 5 4
1 0 1 5 3 2
2 7 3 4 3 2
3 2 5 9 8 7
1 2 8 1 3 2
6 5 2 3 4 1
6 9 1 9 6 1 4 6
7 7 5 2 7 4 7 6 1
6 4 9 4 10 3 4 7 5
10 9 8 4 10 8 3 10 10
8 7 4 8 2 2 2 2 2
1 3 9 6 9 1 6 1 9
6 4 3 10 5 7 8 7 2
5 5 3 3 3 4 3 5
4 5 9 1 8
1 9 3 1 8
2 1 3 5 10
3 6 6 2 7
2 8 8 0 8

(输出)

#1 27
#2 53
#3 8

 

思路分析:
问题可概括为:A点,B点在D点汇合,然后到达C点
分别求出A,B,C点到所有点的最短路径,每个点i的最短路径=A到i+B到i+C到i-2*当前点i的权值-C点的权值
然后遍历所有点,求出距离最短的路径

 

package pro.dijkstra;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.StringTokenizer;
/**
 * 思路分析:
 * 问题可概括为:A点,B点在D点汇合,然后到达C点
 * 分别求出A,B,C点到所有点的最短路径,每个点i的最短路径=A到i+B到i+C到i-2*当前点i的权值-C点的权值
 * 然后遍历所有点,求出距离最短的路径
 * @author XA-GDD
 *
 */
public class Travel_0622 {
	static int T,N,M,R1,C1,R2,C2,R3,C3;
	static int _max_Nval = 500;
	static int _max_Mval = 500;
	static int [][] cost = new int[_max_Nval+1][_max_Mval+1]; 
	static int [][][] minCost = new int [_max_Nval+1][_max_Mval+1][4]; //最小花费
	static int [][] visited = new int[_max_Nval+1][_max_Mval+1]; 
	static int [][] dir = {{-1,0},{0,1},{1,0},{0,-1}}; //方向
	static long ANS;
	public static void main(String[] args) throws IOException {
		System.setIn(new FileInputStream("D:\\workspace\\eclipse-workspace\\sw_pro\\test_case\\sample_input_0622.txt"));
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		T = Integer.parseInt(st.nextToken());
		for(int testCase=1;testCase<=T;testCase++) {
			init();
			st = new StringTokenizer(br.readLine());
			N = Integer.parseInt(st.nextToken());
			M = Integer.parseInt(st.nextToken());
			R1 = Integer.parseInt(st.nextToken());
			C1 = Integer.parseInt(st.nextToken());
			R2 = Integer.parseInt(st.nextToken());
			C2 = Integer.parseInt(st.nextToken());
			R3 = Integer.parseInt(st.nextToken());
			C3 = Integer.parseInt(st.nextToken());
			init();
			for(int i=1;i<=N;i++) {
				st = new StringTokenizer(br.readLine());
				for(int j=1;j<=M;j++) {
					cost[i][j] = Integer.parseInt(st.nextToken());
				}
			}
			
			dijkstra(new int[] {R1,C1},1); //(R1,C1)点到所有点的最短距离
			dijkstra(new int[] {R2,C2},2); //(R2,C2)点到所有点的最短距离			
			dijkstra(new int[] {R3,C3},3); //(R3,C3)点到所有点的最短距离

			for(int i=1;i<=N;i++) {
				for(int j=1;j<=M;j++) {
					ANS = Math.min(ANS, minCost[i][j][1]+minCost[i][j][2]+minCost[i][j][3]-2*cost[i][j]-cost[R3][C3]);
				}
			}
			System.out.println("#"+testCase+" "+ANS);
		}

	}
	
	static void init() {
		ANS=Long.MAX_VALUE;
		for(int i=0;i<cost.length;i++) {
			Arrays.fill(cost[i], 0);
			Arrays.fill(visited[i], 0);
		}
		for(int i=1;i<=N;i++) {
			for(int j=1;j<=M;j++) {
				Arrays.fill(minCost[i][j], Integer.MAX_VALUE>>1);
			}
		}
	}
	
	static void dijkstra(int [] start, int bound) {
		PriorityQueue<int []> pq = new PriorityQueue<int[]>(new Comparator<int []>() {
			@Override
			public int compare(int[] o1, int[] o2) {				
				return o1[2]-o2[2];
			}
		});	
		
		//每次调用都需要初始化,不然第二个点和第三个点求最短路径时就不遍历了
		for(int i=0;i<visited.length;i++) {
			Arrays.fill(visited[i], 0);
		}
		
		minCost[start[0]][start[1]][bound] = cost[start[0]][start[1]];
		pq.add(new int [] {start[0],start[1],minCost[start[0]][start[1]][bound]});
		
		while(!pq.isEmpty()) {
			int [] curr = pq.poll();

			if(visited[curr[0]][curr[1]]==1) {
				continue;
			}
			visited[curr[0]][curr[1]] = 1;
			for(int i=0;i<4;i++) {
				int x = curr[0] + dir[i][0];
				int y = curr[1] + dir[i][1];
				if(isValid(x,y)) {
					if(minCost[x][y][bound]>minCost[curr[0]][curr[1]][bound]+cost[x][y]) {
						minCost[x][y][bound] = minCost[curr[0]][curr[1]][bound]+cost[x][y];
						
						pq.add(new int[] {x,y,minCost[x][y][bound]});
					}
				}
			}
		}
	}
	
	static boolean isValid(int x,int y) {
		return x>0&&x<=N&&y>0&&y<=M;
	}

}

  

标签:出行,10,int,Travel,Dijkstra,static,new,通行费,城市
来源: https://www.cnblogs.com/smile_to_warm/p/15130047.html