731.毕业旅行问题(java DP)

小明目前在做一份毕业旅行的规划。

打算从北京出发,分别去若干个城市,然后再回到北京,每个城市之间均乘坐高铁,且每个城市只去一次。

由于经费有限,小明希望能够通过合理的路线安排尽可能的省些路上的花销。

给定一组城市和每对城市之间的火车票的价钱,找到每个城市只访问一次并返回起点的最小车费花销。

注意:北京为 1 号城市。

输入格式

第一行包含一个正整数 n,表示城市个数。

接下来输入一个 n行 n 列的矩阵,表示城市间的车票价钱。

输出格式

输出一个整数,表示最小车费花销。

数据范围

1<n≤20,包括北京
车票价格均不超过 1000 元。

输入样例:
4
0 2 6 5
2 0 4 4
6 4 0 2
5 4 2 0
输出样例:
13
说明

共 4 个城市,城市 1 和城市 1 的车费为 0,城市 1 和城市 2 之间的车费为 2,城市 1 和城市 3 之间的车费为 6,城市 1 和城市 4 之间的车费为 5,以此类推。

假设任意两个城市之间均有单程票可买,且价格均在 10001000 元以内,无需考虑极端情况。

解题代码:

import java.util.Scanner;

public class Main {
    static final int N = 20;
    static final int M = 1 << N;
    static final int INF = 0x3f3f3f3f;

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int[][] w = new int[N][N];

        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                w[i][j] = scanner.nextInt();
            }
        }

        int[][] f = new int[M][N];
        for (int i = 0; i < M; i++) {
            for (int j = 0; j < N; j++) {
                f[i][j] = INF;
            }
        }
        f[1][0] = 0;

        for (int i = 1; i < 1 << n; i += 2) {
            for (int j = 0; j < n; j++) {
                if ((i >> j & 1) == 1) {
                    for (int k = 0; k < n; k++) {
                        if ((i - (1 << j) >> k & 1) == 1) {
                            f[i][j] = Math.min(f[i][j], f[i - (1 << j)][k] + w[k][j]);
                        }
                    }
                }
            }
        }

        int res = INF;
        for (int i = 1; i < n; i++) {
            res = Math.min(res, f[(1 << n) - 1][i] + w[i][0]);
        }

        System.out.println(res);
    }
}

解题思路:

1. 首先,通过一个二维数组来表示城市之间的车票价钱,数组 `w[N][N]` 存储了城市间的车票价格。

2. 创建一个二维数组 `f[M][N]`,其中 `M = 1 << N`,`N` 是城市的个数。`f[i][j]` 表示在访问完城市集合 `i` 的情况下,最后一次访问的城市是 `j` 的最小花销。

3. 初始化 `f` 数组,将所有元素初始化为一个较大的值,表示初始状态下还没有计算出最小花销。

4. 从起始城市出发,遍历所有可能的访问城市的组合,并计算花费。外层循环遍历所有可能的城市组合 `i`,内层循环遍历城市 `j`,若城市 `j` 在组合 `i` 中,则遍历所有可能的上一个城市 `k`(注意,`k` 也必须在组合 `i` 中),更新 `f[i][j]` 的最小值。

5. 最后,遍历所有城市作为结束城市,并找到返回起点的最小花销。

6. 输出最小花销。

总的来说,是通过动态规划来计算每个状态下的最小花销,然后在结束城市为起点的情况下找到最小的花销。

旅行问题(Traveling Salesman Problem,TSP)是指给定一个城市的集合和每对城市之间的距离,求解访问每一座城市一次并回到起始城市的最短回路。这是一个NP难问题,因此需要使用动态规划算法来求解。以下是Java实现动态规划求解旅行问题的示例代码: ```java public class TSP { private int[][] distance; private int numCities; public TSP(int[][] distance) { this.distance = distance; this.numCities = distance.length; } public int tsp() { int[][] dp = new int[1 << numCities][numCities]; for (int i = 0; i < (1 << numCities); i++) { Arrays.fill(dp[i], Integer.MAX_VALUE); } dp[1][0] = 0; for (int mask = 1; mask < (1 << numCities); mask += 2) { for (int i = 0; i < numCities; i++) { if ((mask & (1 << i)) != 0) { for (int j = 0; j < numCities; j++) { if ((mask & (1 << j)) != 0 && i != j) { dp[mask][i] = Math.min(dp[mask][i], dp[mask ^ (1 << i)][j] + distance[j][i]); } } } } } int res = Integer.MAX_VALUE; for (int i = 1; i < numCities; i++) { res = Math.min(res, dp[(1 << numCities) - 1][i] + distance[i][0]); } return res; } public static void main(String[] args) { int[][] distance = { {0, 10, 15, 20}, {10, 0, 35, 25}, {15, 35, 0, 30}, {20, 25, 30, 0} }; TSP tsp = new TSP(distance); int shortestPath = tsp.tsp(); System.out.println("The shortest path is " + shortestPath); } } ``` 该代码使用二进制状态压缩来表示已访问的城市集合,用dp[mask][i]表示访问集合mask中所有城市且以i为终点的最短路径,其中mask中的第i位表示城市i是否已访问。最终答案为dp[(1 << numCities) - 1][i] + distance[i][0],其中i为任意一个城市,表示访问所有城市回到起点的最短路径。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值