城市个数n(1<n≤20,包括北京)
城市间的车票价钱 n行n列的矩阵 m[n][n]
最小车费花销 s
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.Arrays; import java.util.HashSet; import java.util.LinkedList; import java.util.Scanner; import java.util.Set; // 注意类名必须为 Main, 不要有任何 package xxx 信息 public class Main { static int res; public static void main(String[] args) { Scanner in = new Scanner(System.in); // 注意 hasNext 和 hasNextLine 的区别 while (in.hasNextInt()) { // 注意 while 处理多个 case int n = in.nextInt(); int[][] matrix = new int[n][n]; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { matrix[i][j] = in.nextInt(); } } long res = getShortestWay(n, matrix); System.out.println(res); } } static long getShortestWay (int n, int[][] matrix) { boolean[] visited = new boolean[n]; Arrays.fill(visited, false); int state_num = (1<<n) - 1; // 途径 1 -> n-1 long[][] dp = new long[n][state_num+1]; for (int i = 0; i < n; i++) { Arrays.fill(dp[i], Integer.MAX_VALUE/2); } Set<Integer> set = new HashSet<>(); for (int i = 1; i < n; i++) { set.add(1<<i); dp[i][1<<i] = matrix[0][i]; } int endState = (1<<n)-2; while (!set.isEmpty()) { Set<Integer> newSet = new HashSet<>(); for (int ss:set) { if (ss == endState) continue; // 当前状态 是 ss for (int i = 1; i < n; i++) { // if (dp[i][ss] == Integer.MAX_VALUE/2) { // continue; // } for (int j = 1; j < n; j++) { if (((1<<j) & ss) != 0 ) continue; // 如果已经访问过, 则取消 int newState = ss | (1<<j); dp[j][newState] = Math.min(dp[j][newState], dp[i][ss] + matrix[i][j]); newSet.add(newState); } } } set = newSet; } long res = Integer.MAX_VALUE/2; for (int i = 1; i < n; i++) { res = Math.min(res, dp[i][endState] + matrix[i][0]); } return res; } }
/* 参考 旅行商问题 :https://blog.csdn.net/qq_39559641/article/details/101209534?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ETopBlog-1.topblog&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ETopBlog-1.topblog&utm_relevant_index=1 */ import java.util.Scanner; public class Main { private void sln() { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int[][] prices = new int[n][n]; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { prices[i][j] = sc.nextInt(); } } int m = 1 << (n-1); int[][] dp = new int[n][m]; // 对dp数组进行初始化 for(int i=0; i<n; i++) { dp[i][0] = prices[i][0]; } for(int j=1; j<m; j++) { for(int i=0; i<n; i++) { dp[i][j] = Integer.MAX_VALUE; // 集合j中包含i城市,就是看j的二进制表达i位置上是不是1,是的话就是包含 if(((j >> (i-1)) & 1) == 1) continue; // 不包含 else { for(int k=1; k<n; k++) { if(((j >> (k-1)) & 1) == 0) continue;// 如果集合j中不包含k城市,就不符合要求 dp[i][j] = Math.min(dp[i][j], prices[i][k] + dp[k][j^(1 << (k-1))]);// 集合j中去掉k城市 } } } } System.out.println(dp[0][m-1]); } public static void main(String[] args) { new Main.sln(); } }
import java.util.*; public class Main{ public static void main(String[] args){ Scanner sc = new Scanner(System.in); int N = sc.nextInt(); int[][] nums = new int[N][N]; for(int i=0; i < N; i++){ for(int j=0; j < N; j++){ nums[i][j] = sc.nextInt(); } } Integer[][] memo = new Integer[(1<<N)][N]; System.out.println(DFS(nums, 0, 0, memo)); } private static int DFS(int[][] nums, int idx, int state, Integer[][] memo){ int n = nums.length; if(state == (1<<n)-2){ //防止出现0-1-2-0-3的情况 return nums[idx][0]; } if(memo[state][idx] != null) return memo[state][idx]; int ret = Integer.MAX_VALUE; for(int i=1; i < n; i++){ if((state & (1<<i)) != 0) continue; ret = Math.min(ret, nums[i][idx] + DFS(nums, i, (state ^ (1<<i)), memo)); } memo[state][idx] = ret; return ret; } }
import java.util.*; public class Main { //备忘录 public static int[][] memo; //自上而下的dp函数 public static int dp(int city, int j, int[][] dist) { //中止条件 if(j == 0) return dist[city][0]; //如果命中,直接返回 if(memo[city][j] != -1) return memo[city][j]; int ans = Integer.MAX_VALUE; for(int i = 1; i < dist.length; i++) { if(((j >> (i-1)) & 1) == 1) { j ^= (1 << (i-1)); //记录这一轮的最小答案 ans = Math.min(ans, dist[city][i]+dp(i, j, dist)); j ^= (1 << (i-1)); } } //添加至备忘录 memo[city][j] = ans; return ans; } public static void main(String[] args) { Scanner in = new Scanner(System.in); int cityNum = in.nextInt();// 城市数目 int[][] dist = new int[cityNum][cityNum]; for (int i = 0; i < dist.length; i++) { for (int j = 0; j < cityNum; j++) { dist[i][j] = in.nextInt(); } } //对1进行左移n-1位,值刚好等于2^(n-1) int V = 1 << (cityNum - 1); memo = new int[cityNum][V]; //初始化memo备忘录 for (int i = 0; i < cityNum; i++) { for(int j = 0; j < V; j++) { memo[i][j] = -1; } } int ans = dp(0 , V-1, dist); System.out.println(ans); } }