問題描述:
給定如圖所示的無向連通圖,假定圖中所有邊的權值都為1,顯然,從源點A到終點T的雖短路徑有多條,求不同的最短路徑的數目。
權值相同的最短路徑問題,則但願點Dijkstra算法退化成廣度優先搜索,假定起點為0,終點為N。
用動態規划的思想:
- 使用兩個輔助數組:
- 步數:step[0...N],記錄從起點到某個頂點i的走的最小步數;
- 路徑條數:path[0...N],記錄從起點到某個頂點的最短路徑的條數;
- 總體思路是:根據步數更新最短路徑的條數。
- 考慮:當從當前頂點i擴散到其某相鄰頂點j時:
- 如果step[j] == 0,說明之前還沒有路徑到達過頂點j;活着step[j] > step[i] + 1,則說明之前有頂點走過這條邊,且步數還要比目前走的路徑長,因此可以用當前路徑i的信息更新j.
- 則step[j] = step[i] + 1;
- path[j] = path[i];
- 如果step[j] == step[i] + 1,說明之前有頂點走過這條邊,並且步數跟從i到j的步數一樣,都是最短路徑,因此更新j.
- step[j] 不變;
- path[j] = path[j] + path[i];
- 如果step[j] == 0,說明之前還沒有路徑到達過頂點j;活着step[j] > step[i] + 1,則說明之前有頂點走過這條邊,且步數還要比目前走的路徑長,因此可以用當前路徑i的信息更新j.
- 用隊列保存目前遍歷的節點。
Code:
class NumOfShortestPath { private int[][] aja = { /*0*/{0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0}, /*1*/{1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0}, /*2*/{0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0}, /*3*/{0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0}, /*4*/{1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0}, /*5*/{0,1,0,0,1,0,1,0,0,1,0,0,0,0,0,0}, /*6*/{0,0,1,0,0,1,0,1,0,0,1,0,0,0,0,0}, /*7*/{0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0}, /*8*/{0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0}, /*9*/{0,0,0,0,0,1,0,0,1,0,1,0,0,1,0,0}, /*10*/{0,0,0,0,0,0,1,0,0,1,0,1,0,0,1,0}, /*11*/{0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1}, /*12*/{0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0}, /*13*/{0,0,0,0,0,0,0,0,0,1,0,0,1,0,1,0}, /*14*/{0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,1}, /*15*/{0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0}, }; public int[][] getData() { return aja; } public int getNumOfShortestPahtes(int[][] edge) { int len = edge.length; int[] step = new int[len]; int[] path = new int[len]; path[0] = 1; Queue<Integer> q = new LinkedList<Integer>(); q.add(0); //將起點放入 while(!q.isEmpty()) { int element = q.remove(); for(int j=1; j<len; j++) { if(edge[element][j] == 1) { if(step[j] == 0 || step[j] > step[element] + 1) { step[j] = step[element] + 1; path[j] = path[element]; q.add(j); } else if(step[j] == step[element] + 1) path[j] += path[element]; } } } return path[len-1]; } }