题目:
1003 Emergency (25 分)
As an emergency rescue team leader of a city, you are given a special map of your country. The map shows several scattered cities connected by some roads. Amount of rescue teams in each city and the length of each road between any pair of cities are marked on the map. When there is an emergency call to you from some other city, your job is to lead your men to the place as quickly as possible, and at the mean time, call up as many hands on the way as possible.
Input Specification:
Each input file contains one test case. For each test case, the first line contains 4 positive integers: N (≤500) - the number of cities (and the cities are numbered from 0 to N−1), M - the number of roads, C1 and C2 - the cities that you are currently in and that you must save, respectively. The next line contains N integers, where the i-th integer is the number of rescue teams in the i-th city. Then M lines follow, each describes a road with three integers c1, c2 and L, which are the pair of cities connected by a road and the length of that road, respectively. It is guaranteed that there exists at least one path from C1 to C2.
Output Specification:
For each test case, print in one line two numbers: the number of different shortest paths between C1 and C2, and the maximum amount of rescue teams you can possibly gather. All the numbers in a line must be separated by exactly one space, and there is no extra space allowed at the end of a line.
Sample Input:
5 6 0 2
1 2 1 5 3
0 1 1
0 2 2
0 3 1
1 2 1
2 4 1
3 4 1
Sample Output:
2 4
意思大致很简单 第一行 分别是M N C1 C2
m代表有m个城市本地的救援队数量 N是N条路径 有A城市到B城市 距离是多少
C1起始点 C2终点
还没做前想法大致是:
递归. 先用一个二维数组把所有城市到城市的路径距离放进去
比如 0 1 1 放在二维数组的(1,0) value=1 正常来说应该放到(0,1)但是反放是因为 终点是城市1的 我们要反向考虑能通往城市1的路径 那么城市1这个"1"就是我们拿来查找的线索,也就是所引用的key 所以很容易在x=1的这一列找到0这个城市能通往1城市
紧接着 举个例子 0是起点 1是终点 我们一共有 0-1,0-4-1,0-3-4-1,0-3-2-1
这个过程中可以发现 我们查找路径的时候是不会计算再次访问的路径的 也就是没人会 0-4-3-0-1 因为这样明显代价高于0-1
那我们需要实现的方法 大致就是 method(int n,List list)
其中list用来存放已经走过的路径 用来限制n不能为list内部元素 即不走重复路线 list末位用来表示 上一个走过的城市
n是当前到达城市 明显 如果n是当前希望的终点 那么函数直接返回(n,list.get[length-1])的值
否则在二维数组中查询X=n的 未重复的Y1....Yn值 把n放入list 返回min{method(Y1,list) , ......method(Y2,list)}
大致如此 明天写代码,先行睡觉
今天的结果是...没算出来 可以用递归算出 最短长度 但是sum和valueSum实在算不出来
而且发现逻辑开始混乱了. 额外收获就是 发现一种floyda方法 可以用三重for循环直接暴力更新一个二维数组
i j代表 起点和终点 e代表可以加入的中间路径点 二维数组存储着i到j的最短长度 如果i j不直接连通则设为无穷大
简单用上图举例 比如 先填满二维数组 某城市到达自己的距离规定为0
0 1 2 9
1 0 2 5
2 2 0 2
9 5 2 0
第一次尝试把e =2加入进去
1--3 就会和1--2--3进行比较 如果1--2--3不小于1--3 1--3值就保持为1到3直达的距离
同理 1--4 和 1--2--4比较 dp[1][4]里实际存放的就是1--2--4
e=3时
1--2就会和1--3--2比较 dp[1][2] 依然放直达距离
1--4 就会和1--3--4比较 实际上 dp[1][4] 现在是dp[1][2]+dp[2][4] 1--3--4 实际就是dp[1][3]+dp[3][4]
假如上面1--3 大于 1--2--3
实际上这里比的就是 1--2--4 和 1--2--3--4的路径和比较
所以一定会把所有情况都计算在内 不会出现 1--2--3--4 中 2和3两个节点不能同时加入的情况
实际操作起来是这样
for (int e = 0; e < cityNum; e++) {
for (int i = 0; i < cityNum; i++) {
for (int j = 0; j < cityNum; j++) {
if (result[i][j] > roadToFrom[i][e] + roadToFrom[e][j]) {
result[i][j] = roadToFrom[i][e] + roadToFrom[e][j];
}
}
}
}
https://www.cnblogs.com/ECJTUACM-873284962/p/6995648.html
在此致谢某健身回家后给我解答的ACM队员
import java.util.Scanner;
/**
* @ClassName ${Name}
* @Description TODO
* @Author < a href="jcsong50@best-inc.com">sqc</a>
* @Date 2019/1/20 19:45
* @Version 1.0
*/
public class PAT3 {
public static Scanner scanner = new Scanner(System.in);
public static void main(String[] args) {
int n = scanner.nextInt();
int m = scanner.nextInt();
int c1 = scanner.nextInt();
int c2 = scanner.nextInt();
int[] values = new int[n];
int[][] locate = new int[n][n];
for(int i=0;i<n;i++){
values[i] = scanner.nextInt();
}
for(int i=0;i<m;i++){
int x= scanner.nextInt();
int y= scanner.nextInt();
int length = scanner.nextInt();
locate[x][y] = length;
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++) {
if (locate[i][j] == 0 && i != j) {
locate[i][j] = 999999;
}
}
}
//存sum
int[][] min =new int[n][n];
//存values
int[][] max = new int[n][n];
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
max[i][j] = values[i]+values[j];
min[i][j]=1;
if(locate[i][j]==Integer.MAX_VALUE){
max[i][j]=0;
}
}
}
for(int e =0;e<n;e++){
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(locate[i][j]==locate[i][e]+locate[e][j]&&e!=i&&e!=j){
min[i][j]++;
max[i][j] = max[i][j]+values[e];
}
if(locate[i][j]>locate[i][e]+locate[e][j]){
locate[i][j] = locate[i][e]+locate[e][j];
min[i][j]=min[i][e]*min[e][j];
max[i][j] = max[i][e]+max[e][j]-values[e];
}
}
}
}
System.out.println(min[c1][c2]+" "+max[c1][c2]);
}
}
样例只过了一个 才得10分很尴尬 而且后面的测试用例明显超时了