[英]Recursive headache
任務 :
給定一個包含整個非負數的二維數組m
,我們將一個“路徑”定義為相鄰單元格的集合(對角線步驟不算作鄰居 )從row == 0 && col == 0
開始row == 0 && col == 0
並以row == m.length - 1 && col == m[0].length - 1
結束row == m.length - 1 && col == m[0].length - 1
。
“路徑”的成本是“路徑”的每個單元中的值的總和。
例:
數組中的兩個可能路徑:
路徑1(虛線)的成本:8 + 4 + 2 + 8 + 9 + 9 + 7 + 5 = 52;
路徑2的成本(實線):8 + 6 + 3 + 8 + 9 + 4 + 1 + 2 + 1 + 7 + 6 + 5 = 60
去做:
寫一個static
接受2D陣列遞歸方法m
充滿整個非負值 ,並打印所有可能的路徑成本的總和(你可以假定m
不是null
也不空)。
方法簽名是(允許重載):
public static void printPathWeights(int [][] m)
我的代碼:
public class Main {
public static void main(String[] args) {
int arr[][] = { { 1, 1, 1 },
{ 1, 1, 1 },
{ 1, 1, 1 }
};
printPathWeights(arr);
}
public static void printPathWeights(int[][] m) {
System.out.println(printPathWeights(m, 0, 0, new int[m.length][m[0].length], 0));
}
/*
* @param map marks the visited cells
*/
private static int printPathWeights(int[][] m, int row, int col, int[][] map, int carrier) {
if (row < 0 || col < 0 || row >= m.length || col >= m[0].length || map[row][col] == 1)
return 0;
if (row == m.length - 1 && col == m[0].length - 1)
return m[row][col] + carrier;
map[row][col] = 1;
return printPathWeights(m, row + 1, col, map, carrier + m[row][col]) +
printPathWeights(m, row - 1, col, map, carrier + m[row][col]) +
printPathWeights(m, row, col + 1, map, carrier + m[row][col]) +
printPathWeights(m, row, col - 1, map, carrier + m[row][col]);
}
}
上述代碼的印刷值為:14
這比預期的少!
運行時:
int arr[][] = { { 1, 1 },
{ 1, 1 }
};
結果是預期的6。
我的代碼有什么問題?
PS:請不要向我提供解決作業的代碼,但要解釋我的代碼有什么問題。
一旦任意路徑到達該單元,代碼就標記訪問的單元。 但是此細胞隨后被標記為所有其他細胞的訪問,並且不再被訪問。 這意味着該算法僅完成路徑的子集,並且一些遍歷在陣列中間的某處中斷以獲得更大的陣列。 您必須將單元格標記為每個路徑單獨訪問。
只需在每次訪問新單元格后重置地圖:
printPathWeights(...)
//analyze the current cell
markCellVisited(currentCell)
int tmp = visitAllNeighbours()
resetVisitedState(currentCell)
return tmp
這將是最有效和最簡單的方法。 由於在訪問單元格后復位了cellstate,因此它將永遠不會保留前一個路徑的標記。
正如Paul所說,代碼所需的更改是在遞歸調用之后恢復被訪問單元的集合。 按預期打印76
。
public class Main {
public static void main(String[] args) {
int arr[][] = { { 1, 1, 1 },
{ 1, 1, 1 },
{ 1, 1, 1 }
};
printPathWeights(arr);
}
public static void printPathWeights(int[][] m) {
System.out.println(printPathWeights(m, 0, 0, new int[m.length][m[0].length], 0));
}
/*
* @param map marks the visited cells
*/
private static int printPathWeights(int[][] m, int row, int col, int[][] map, int carrier) {
if (row < 0 || col < 0 || row >= m.length || col >= m[0].length || map[row][col] == 1)
return 0;
if (row == m.length - 1 && col == m[0].length - 1)
return m[row][col] + carrier;
map[row][col] = 1;
int result = printPathWeights(m, row + 1, col, map, carrier + m[row][col]) +
printPathWeights(m, row - 1, col, map, carrier + m[row][col]) +
printPathWeights(m, row, col + 1, map, carrier + m[row][col]) +
printPathWeights(m, row, col - 1, map, carrier + m[row][col]);
map[row][col] = 0; // Here
return result;
}
}
在我看來,你只在一次遞歸中計算所有單元格的權重之和。 但不考慮路徑可能相交的事實,並且任何兩條路徑都可以有共同的單元格。就像圖中所示的兩條路徑具有共同的單元格並且必須添加兩次
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.