2019阿里校招测评题 光明小学完全图最短路径问题
題目:
光明小學的小朋友們要舉行一年一度的接力跑大賽了,但是小朋友們卻遇到了一個難題:設計接力跑大賽的線路,你能幫助他們完成這項工作么?
光明小學可以抽象成一張有N個節點的圖,每兩點間都有一條道路相連。光明小學的每個班都有M個學生,所以你要為他們設計出一條恰好經過M條邊的路徑。
光明小學的小朋友們希望全盤考慮所有的因素,所以你需要把任意兩點間經過M條邊的最短路徑的距離輸出出來以供參考。
你需要設計這樣一個函數:
res[][] Solve( N, M, map[][]);
注意:map必然是N * N的二維數組,且map[i][j] == map[j][i],map[i][i] == 0,-1e8 <= map[i][j] <= 1e8。(道路全部是無向邊,無自環)2 <= N <= 100, 2 <= M <= 1e6。
map數組表示了一張稠密圖,其中任意兩個不同節點i,j間都有一條邊,邊的長度為map[i][j]。N表示其中的節點數。
你要返回的數組也必然是一個N * N的二維數組,表示從i出發走到j,經過M條邊的最短路徑
你的路徑中應考慮包含重復邊的情況。
樣例:
N = 3
M = 2
map = {
?{0, 2, 3},
?{2, 0, 1},
?{3, 1, 0}
}
輸出結果result為:
result = {
?{4, 4, 3},
?{4, 2, 5},
?{3, 5, 2}
}
輸入樣例:
3
2
3 3?
0 2 3
2 0 1
3 1 0
輸出樣例:
[[4, 4, 3],
[4, 2, 5],
[3, 5, 2]]
解題思路:
首先第一點是肯定的,全排列肯定是可以求出解的,但是時間復雜度那肯定是爆炸的,當然,30分鐘的時間里面能把全排列寫出來也是可以的了我感覺。
但是還是想試試動態規劃能不能求解,我們把每一步的中間結果都存下來,相當于對搜索進行了剪枝操作。當然,動態規劃是基于以下的假設:
如果從點s到點t存在最小路徑而且正好經過點c,那從s到c的所有路徑當中,這條s->c一定是最短路徑。
很好理解,如果當前這條s->c(我們稱之為l1)不是最短的話,那肯定存在一條s->c路徑(l2)最短,那走2到t肯定比走l1到t短,所以l1肯定就被替換掉了。
代碼實現:
全排列版:
public class Test {private static int[][] resultMap;private static int times = 0;public static void main(String[] args) {Scanner scanner = new Scanner(System.in);// 初始化int N = scanner.nextInt();int M = scanner.nextInt();int[][] map = new int[N][N];for (int i = 0; i < N; i ++) {for (int j = 0; j < N; j ++) {map[i][j] = scanner.nextInt();}}resultMap = new int[N][N];// 執行for (int i = 0; i < N; i ++) {route(map, N, M, 1, i, i, 0);}// 打印System.out.println("total recursion: " + times);for (int i = 0; i < N; i ++) {for (int j = 0; j < N; j ++) {System.out.print(resultMap[i][j] + " ");}System.out.println("");}}private static void route(int[][] map, int N, int M, int step, int head, int now, int cost) {times ++;if (step > M) {resultMap[head][now] = resultMap[head][now] == 0 ? cost : (Math.min(resultMap[head][now], cost));return;}for (int i = 0; i < N; i ++) {if (i == now) continue;route(map, N, M, step + 1, head, i, cost + map[now][i]);}} }動態規劃版:
public class Test {private static int[][][] resultMap;private static int times = 0;public static void main(String[] args) {Scanner scanner = new Scanner(System.in);// 初始化int N = scanner.nextInt();int M = scanner.nextInt();int[][] map = new int[N][N];for (int i = 0; i < N; i ++) {for (int j = 0; j < N; j ++) {map[i][j] = scanner.nextInt();}}resultMap = new int[M][N][N];// 執行,動態規劃// 初始化步數為1的情況for (int i = 0; i < N; i ++) {for (int j = 0; j < N; j ++) {resultMap[0][i][j] = map[i][j];}}// 更新步數2-M的情況for (int k = 1; k < M; k ++) {for (int i = 0; i < N; i ++) {for (int j = 0; j < N; j ++) {for (int p = 0; p < N; p ++) {times ++;if (p == j || resultMap[k - 1][i][p] == 0) continue;resultMap[k][i][j] = Math.min(resultMap[k][i][j] == 0 ? Integer.MAX_VALUE : resultMap[k][i][j], resultMap[k - 1][i][p] + map[p][j]);}}}}// 打印System.out.println("total recursion: " + times);for (int i = 0; i < N; i ++) {for (int j = 0; j < N; j ++) {System.out.print(resultMap[resultMap.length - 1][i][j] + " ");}System.out.println("");}} }測試結果
3 2 0 2 3 2 0 1 3 1 0 total recursion: 21 4 4 3 4 2 5 3 5 2?
總結
以上是生活随笔為你收集整理的2019阿里校招测评题 光明小学完全图最短路径问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 面向对象方法学与结构化方法学的异同
- 下一篇: NESI—概念和内涵