字节编程题 毕业旅行问题

小明目前在做一份毕业旅行的规划。打算从北京出发,分别去若干个城市,然后再回到北京,每个城市之间均乘坐高铁,且每个城市只去一次。由于经费有限,希望能够通过合理的路线安排尽可能的省一些路上的花销。给定一组城市和每对城市之间的火车票的价钱,找到每个城市只访问一次并返回起点的最小车费花销。


输入描述:
城市个数n(1<n≤20,包括北京)
城市间的车票价钱 n行n列的矩阵 m[n][n]
输出描述:
最小车费花销 s
示例1
输入
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,依次类推。假设任意两个城市之间均有单程票可购买,且票价在1000元以内,无需考虑极端情况。
import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int[][] dist = new int[n][n];
        for (int i = 0; i < dist.length; i++) {
            for (int j = 0; j < n; j++) {
                dist[i][j] = in.nextInt();
            }
        }
        in.close();
        //随便挑一个作为起点,为方便计算,就选择0城市就好,
        // 那么对应的事件可以理解为从0号城市出发去(1号、2号、3号城市)最后回到0号城市,其中中间的1、2、3之间的顺序不清楚怎么去的。
        //但是可以发现事件最小消耗为min(从0->1的距离+从1号到{2号、3号}最后回到0的距离、
        // 从0->2的距离+从2号到{1号、3号}最后回到0的距离、
        // 从0->3的距离+从1号到{1号、2号}最后回到0的距离)。
        // 用bit第几位是否为1表示当前事件有哪几号城市。{2号、3号}——> 110;
        
        int V = 1 << (n - 1);
        int[][] dp = new int[n][V];
        dp[0][0] = 0;
        for (int j = 0; j < V; j++) {
            for (int i = 0; i < n; i++) {
                if (j == 0) {
                    //表示从第i个城市到第j(0)个城市的最小路径。正好就是第i个城市去第0个城市的距离。
                    dp[i][j] = dist[i][j] + dp[0][0];
                } else {
                    dp[i][j] = Integer.MAX_VALUE;
                    for (int k = 1; k < n; k++) {
                        //表示第k位城市。
                        int index = (1 << (k - 1));
                        //当前的dp应该是遍历了j城市集的每一个城市对应的子dp+i到k的距离,求得的其中的最小的那个值;
                        if ((index & j) > 0) {
                            //找到其中的一个k;

                            //表示j城市集内除了第k位其他的别的城市
                            int other = j ^ index;
                            dp[i][j] = Math.min(dist[i][k] + dp[k][other], dp[i][j]);
                        }
                    }
                }
            }
        }
        System.out.println(dp[0][V - 1]);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北顾丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值