ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

出行 - Travel - Dijkstra

2022-01-20 21:02:17  阅读:160  来源: 互联网

标签:出行 10 int Travel Dijkstra static new 通行费 城市


出行

时间限制:最多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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有