PAT甲级 1003 java做法 及常见错误分析

题目:

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, C​1​​ and C​2​​ - 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 c​1​​, c​2​​ 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 C​1​​ to C​2​​.

Output Specification:

For each test case, print in one line two numbers: the number of different shortest paths between C​1​​ and C​2​​, 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分很尴尬 而且后面的测试用例明显超时了

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值