题意:
计算使两个城市间距离为最小距离的路径个数,但是还要保证城市值(即能带的医疗队)最大
分析:
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;
}
}