• leetcode 787 K 站中最便宜的航班 DP


      状态转移方程的定义为:dp( K,i ) 表示经历 K 站乘坐到 flight[i] 航班终点的最低票价。

      因为 flight 中的元素存在前后置关系,所以乘坐某航班的上一航班的集合是可以确定的。

      dp( K,i ) = Math.min( dp( K-1,j ) ),其中 j 为可以作为上一趟航班的航班下标集合。

    /**
         * @Author Niuxy
         * @Date 2020/10/18 4:53 下午
         * @Description 按出发地选中开头航班后,不断通过比较目的地与下一出发地寻找可能的下一航班
         * 因为每趟航班的目的地是确定的,不管从哪条路线来到该航班,最终结果只受剩余可乘坐航班次数的限制
         * 因此可以通过航班坐标 flag 及剩余可乘坐航班次数 K 来进行结果的缓存
         * 那么可以以这两个维度进行 DP 递推
         */
        public final int findCheapestPriceDP(int n, int[][] flights, int src, int dst, int K) {
            int len = flights.length;
            int[][] cache = new int[K + 1][len];
            int re = Integer.MAX_VALUE;
            for (int i = 0; i < cache[0].length; i++) {
                if (flights[i][0] != src) continue;
                if (flights[i][1] == dst) re = Math.min(re, flights[i][2]);
                else cache[K][i] = flights[i][2];
            }
            for (int i = K - 1; i >= 0; i--) {
                for (int j = 0; j < len; j++) {
                    int minPreCost = Integer.MAX_VALUE;
                    for (int k = 0; k < len; k++) {
                        if (cache[i + 1][k] == 0 || flights[j][0] != flights[k][1]) continue;
                        else minPreCost = Math.min(minPreCost, cache[i + 1][k]);
                    }
                    if (minPreCost != Integer.MAX_VALUE)
                        if (flights[j][1] == dst) re = Math.min(re, minPreCost + flights[j][2]);
                        else cache[i][j] = minPreCost + flights[j][2];
                }
            }
            return re == Integer.MAX_VALUE ? -1 : re;
        }

      在第三层 for 循环中,我们在以 O(N) 的时间复杂度寻找上一趟航班可能的下标。整个状态转移方程没有用到参数 n 。

      如果以 n 为维度建立缓存表,遍历 flight 时可以直接以 O(1) 的时间复杂度找到上一趟航班;另外,DP 的过程只涉及到 K 与 K-1 行,可以借此优化空间复杂度:

        public final int findCheapestPriceDP2(int n, int[][] flights, int src, int dst, int K) {
            int flag = Integer.MAX_VALUE / 2;
            int[][] dp = new int[2][n];
            dp[0][src] = dp[1][src] = 0;
            Arrays.fill(dp[0], flag);
            Arrays.fill(dp[1], flag);
            for (int k = 0; k <= K; k++) {
                for (int[] info : flights) {
                    dp[k & 1][info[1]] = Math.min(dp[k & 1][info[1]], dp[~k & 1][info[0]] + info[2]);
                }
            }
            return dp[K & 1][dst] < Integer.MAX_VALUE / 2 ? dp[K & 1][dst] : -1;
        }

      JS 写法:

    /**
     * @param {number} n
     * @param {number[][]} flights
     * @param {number} src
     * @param {number} dst
     * @param {number} K
     * @return {number}
     */
    var findCheapestPrice = function (n, flights, src, dst, K) {
        let dp = [];
        for (let i = 0; i < K + 2; i++) {
            dp.push(new Array(n).fill(Number.MAX_VALUE));
            dp[i][src] = 0;
        }
        let an = Number.MAX_VALUE;
        for (let i = 1; i < K + 2; i++) {
            for (let j = 0; j < flights.length; j++) {
                dp[i][flights[j][1]] = Math.min(dp[i][flights[j][1]], dp[i - 1][flights[j][0]] + flights[j][2]);
            }
        }
        return dp[K + 1][dst] == Number.MAX_VALUE ? -1 : dp[K + 1][dst];
    };

      

    当你看清人们的真相,于是你知道了,你可以忍受孤独
  • 相关阅读:
    面向对象--接口的实际应用--制定标准
    iconv命令 gbk 转 UTF-8
    map,list
    springMVC配置(XML配置详解)
    关于git-Git 分支管理和冲突解决
    使用Intellij idea开发
    Centos7.2 Install subversion server
    Nginx 多域名配置
    Nginx 解析PHP的原理 | CGI、FastCGI及php-fpm的关系
    Centos7 Yum安装 PHP5.5,5.6,7.0
  • 原文地址:https://www.cnblogs.com/niuyourou/p/13906589.html
Copyright © 2020-2023  润新知