【TSP】C000_NK_字节笔试题_毕业旅行问题(二进制枚举)

一、Problem

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

输入描述:

城市个数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

输出例子1:
13

例子说明1:
共 4 个城市,城市 1 和城市 1 的车费为0,城市 1 和城市 2 之间的车费为 2,
城市 1 和城市 3 之间的车费为 6,城市 1 和城市 4 之间的车费为 5,依次类推。
假设任意两个城市之间均有单程票可购买,且票价在1000元以内,无需考虑极端情况。

二、Solution

方法一:dp

  • 定义状态
    • dp[i][j]dp[i][j] 表示从城市 ii 出发,经过城市集合 jj 中各个顶点仅一次,并回到发点 ss 的最短距离。
  • 思考状态转移方程
    • 如果 jj 是空集,dp[i][j] = dp[i][0] = dist[i][0] 表示从 ii 出发,经过 0 个城市,并回到出发点 s 的最短距离,也就是从城市 ii 回到出发城市 ss 的最短路距离了。
    • 否则,dp[i][k] = min(dp[i][j], dp[i][k] + dp[i][j ^ (1 <<(k-1))])j ^ (1 << (k - 1)) 表示从 ii 出发,经过城市集合 jj(不包含城市 kk),并回到出发点 ss 的最短距离。
  • 思考初始化:
    • dp[0...i][0]=dist[0...i][0]dp[0...i][0] = dist[0...i][0] 同上
  • 思考输出dp[s][tot]dp[s][tot]tot = 1 << (n-1) - 1

java 位运算优先级杀我:(1 << (n - 1)) - 1 这样写是对的,但 1 << (n - 1) - 1 这样写是错的,原因是左移运算符优先级比减法低。

import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
	static class Solution {
		void init() {
			Scanner sc = new Scanner(new BufferedInputStream(System.in));
			int n = sc.nextInt(), tot = (1 << (n - 1)) - 1, g[][] = new int[n][n], dp[][] = new int[n][1<<n];
			for (int i = 0; i < n; i++)
			for (int j = 0; j < n; j++)	g[i][j] = sc.nextInt();
			for (int i = 0; i < n; i++)	dp[i][0] = g[i][0];
			
			for (int j = 1; j <= tot; j++)
            for (int i = 0; i < n; i++) {
                dp[i][j] = Integer.MAX_VALUE;
                if ((j & (1 << (i-1))) != 0)
                    continue;
                for (int k = 1; k < n; k++) {
                    if ((j & (1 << (k-1))) > 0)
                        dp[i][j] = Math.min(dp[i][j], g[i][k] + dp[k][j ^ (1 << (k-1))]);
                }
            }
			System.out.println(dp[0][tot]);
		}
	}
    public static void main(String[] args) throws IOException {  
        Solution s = new Solution();
		s.init();
    }
}

复杂度分析

  • 时间复杂度:O(n2×2n)O(n^2 × 2^n)
  • 空间复杂度:O(n2)O(n^2)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章