代碼核心缺陷
- 賦值寫成比較:
b[i][j]==1; 應為 b[i][j]=1;,導致訪問標記永不生效,重複訪問同一單元格。
- 遞歸終止條件位置錯誤:
if(num==m*n) return; 放在遞歸調用之後,且所有方向判斷均為獨立 if 而非 else if,導致返回後繼續執行後續 if 進入下一層遞歸。
- 方向轉換邏輯混亂:
s++ 後未重新驗證邊界,直接遞歸調用新坐標,極易越界或陷入無限轉向。
修正版核心邏輯
void solve(int i, int j) {
// 1. 邊界與訪問檢查
if (i < 0 || i >= m || j < 0 || j >= n || b[i][j]) return;
// 2. 訪問當前單元格
printf("%d ", a[i][j]);
b[i][j] = 1; // 修正:賦值
if (++num == m * n) return; // 修正:前置遞增並檢查終止
// 3. 嘗試按當前方向前進
int ni = i, nj = j;
switch (s % 4) {
case 0: ni = i + 1; break; // 向下
case 1: nj = j + 1; break; // 向右
case 2: ni = i - 1; break; // 向上
case 3: nj = j - 1; break; // 向左
}
// 4. 若下一步合法且未訪問,繼續;否則轉向
if (ni >= 0 && ni < m && nj >= 0 && nj < n && !b[ni][nj]) {
solve(ni, nj);
} else {
s++; // 轉向
solve(i, j); // 原地重新嘗試新方向
}
}
關鍵修正點
- 統一入口檢查,避免重複代碼。
- 使用
switch 替換多 if,確保單一方向執行。
- 終止條件前置,滿足即返回,不再執行後續邏輯。
- 轉向後原地遞歸,由入口檢查重新計算下一步。
調試建議
- 添加
printf("solve(%d,%d) dir=%d\n", i, j, s%4); 觀察遞歸路徑。
- 小矩陣(2x2, 3x3)手動跟蹤驗證邏輯。
- 考慮改用迭代 + 方向向量數組,完全避免遞歸棧溢出風險。