1003

题意:

计算使两个城市间距离为最小距离的路径个数,但是还要保证城市值(即能带的医疗队)最大

分析:

1、首先要知道怎么求取最短路径(如Dijsktra或者Prime算法的思想啦,这里用的是Dijsktra,并且是在百度了其思想原理之后第一次亲手实现的代码,好激动有木有^_^)

2、看清题意,是要计算使两个点之间最短距离为最短距离的路径个数,不是最短路径(一开始很兴奋的提交了多次都不对,又看一遍题才幡然醒悟,唉)

那么怎么求呢?

a、首先设想一下现实生活中求取这样的路径个数的方法。如果城市A到城市C的最短路径的个数为a,然后城市A到城市E的最短路径是通过A到C的最短路径加上C到E的直接路径,那么A到E的最短路径的个数为A到C的最短路径的路径个数;如果A到E的最短路径已经是 A到C的最短路径加上C到E的直接路径的值了,那么A到E的最短路径的路径个数为A到E的本来的路径个数加上A到C的路径个数,这是很显然的事实!!


b、也就是说A到E的路径个数更新的时间点只有两个,就是在A到E的现有最短路径小于等于 A到C的最短路径与C到E的路径的和 的时候;

小于的时候,说明A到E的最短路径要更新,那么个数就等于A到C的个数;

等于的时候,说明A到E的最短路径不需要更新,那么个数应该等于 之前A到E的个数再加上现有方法(A到C加上C到E)即A到C的个数

其他时间点没有更新!!!

c、然后,重要的就是A到每个点的初始化问题了,题目中明确说明,保证至少有一条路径,所以可以全部初始化为1;

总结:之前写代码全是用到那个算法,然后去找哪个算法的代码,粘贴复制过来,需要改动的地方再稍加改动,然后记忆某个算法的时候都是记忆算法的代码,进来才发现真是大错特错了!!!怪不得学了这么些年都还是个渣渣啊!

学习算法的方法应该是,记忆算法的思想原理,就是你先用人类能理解的自然语言清楚的描述出一步步该怎么做,并且按照测试用例用人类的思路过一遍。然后,基于此,无论什么语言,你都可以实现该算法的!!!

语言只是个解决问题的工具而已,你记忆语言是没有用的,要记忆最根本的,思想原理!!!赞!!O(∩_∩)O~

下面粘贴一下自己第一次实现的Dijkstra^_^

package AdvancedLevelPractice;

import java.util.Scanner;


public class pat1003 {

	public static final int max = 0Xffff;
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		try {
			Scanner scanner = new Scanner(System.in);
			
			int N = scanner.nextInt();
			int M = scanner.nextInt();
			int C1 = scanner.nextInt();
			int C2 = scanner.nextInt();
			
			int[] rescueTeams = new int[N];	
			int[][] distances = new int[N][N];
			
			for(int i = 0; i < N; i++){
				rescueTeams[i] = scanner.nextInt();
				for(int j = 0; j < N; j++){
					distances[i][j] = max;
				}
				distances[i][i] = 0;
			}
			
			for(int i = 0; i < M; i++){
				int cc1 = scanner.nextInt();
				int cc2 = scanner.nextInt();
				int d = scanner.nextInt();
				distances[cc1][cc2] = distances[cc2][cc1] = d;
			}
			
			int[] results = getShortestPath(C1, C2, N, distances, rescueTeams);
			
			System.out.print(results[0]+" "+results[1]);
			
			scanner.close();
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}
	private static int[] getShortestPath(int S, int D, int N, int[][] distances, int[] rescueTeams) {
		// TODO Auto-generated method stub
		
		int[] length = new int[N];
		int[] flag = new int[N];
		int[] teamNum = new int[N];
		int[] count = new int[N];
		
		for(int i = 0; i < N; i++){
			length[i] = distances[S][i];
			flag[i] = 1;
			count[i] = 1;
			if(distances[S][i] != max ){	
				if(distances[S][i] == 0){
					teamNum[i] = rescueTeams[i];
				}
				else {
					teamNum[i] = rescueTeams[i] + rescueTeams[S];
				}	
			}
			else{
				teamNum[i] = 0;
			}
			
		}
		flag[S] = 0;
		//teamNum[S] = rescueTeams[S];
		int minDistance, index = S;
		
		for(int i = 0; i < N - 1; i++){
			minDistance = max;
			for(int j = 0; j < N; j++){
				if(flag[j] != 0 && minDistance > length[j]){
					minDistance = length[j];
					index = j;	
				}
			}
			//teamNum[index] = teamNum[S] + rescueTeams[index];
			flag[index] = 0;
			
			for(int k = 0; k < N; k++){
				int tmp = length[index] + distances[index][k];
				if(flag[k] != 0 && length[k] >= tmp){
					
					int num = teamNum[index] + rescueTeams[k];
					if(length[k] > tmp){
						count[k] = count[index];
						length[k] = tmp;
						teamNum[k] = num;
					}
					else {
						count[k] = count[k] + count[index];
						if (teamNum[k] < num) {
							teamNum[k] = num;
						}
					}
				}
			}
		}
		/*
		for(int i = 0; i < N; i++){
			System.out.println(length[i]+"\t"+teamNum[i]+"\t"+count[i]);
		}
		*/
		int[] results = new int[2];
		results[0] = count[D];
		results[1] = teamNum[D];
		return results;
	}

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值