在 p×q 棋盤(1 ≤ p×q ≤ 26)上,騎士(馬)走「日」字步(2 格直 + 1 格橫)。找出一條路徑,使騎士恰好走遍每個格子一次(漢密爾頓路徑)。可從任意格子起始,輸出字典序最小的路徑。無解輸出 "impossible"。
int status[100][100]; // 訪問標記
int vex[8] = {-2,-2,2,2,-1,-1,1,1}; // 8 向行位移
int vey[8] = {-1,1,-1,1,-2,2,-2,2}; // 8 向列位移
char path1[1000]; // 最佳路徑列字母
int path2[1000]; // 最佳路徑行號
char prepath1[1000]; // 當前探索路徑
int prepath2[1000];
int top, n, m, key, k, s; // 全域狀態變數
void dfs(int x, int y) {
for (int i = 0; i <= 7; i++) { // 嘗試 8 個方向
int xend = x + vex[i];
int yend = y + vey[i];
if (合法且未訪問) {
標記訪問;
記錄路徑;
s++; // 步數計數
if (s == n*m) { // 走完所有格
更新最佳路徑(字典序比較);
} else {
dfs(xend, yend); // 遞迴深入
}
回溯:撤銷標記、路徑、步數;
}
}
}
// 比較 prepath (新路徑) 與 path (當前最佳)
int change = -1;
for (int j = 0; j <= n*m-1; j++) {
if (path1[j] > prepath1[j]) { change = 1; break; } // 新路徑字母較小
else if (path1[j] < prepath1[j]) { change = 0; break; }
else { // 字母相同,比數字
if (path2[j] > prepath2[j]) { change = 1; break; }
else if (path2[j] < prepath2[j]) { change = 0; break; }
}
}
if (change == 1) 複製 prepath 到 path;
int main() {
scanf("%d", &t);
for (tem=1; t--; tem++) {
scanf("%d %d", &n, &m);
if (n==1 && m==1) { 輸出 A1; continue; }
key = 0; // 是否找到解
for (i=1; i<=n; i++) {
for (j=1; j<=m; j++) {
初始化狀態;
從 (i,j) 起始 DFS;
if (找到解) break;
}
if (找到解) break;
}
輸出結果;
}
}
輸入: 3 1 1 2 3 4 3 輸出: Scenario #1: A1 Scenario #2: impossible Scenario #3: A1B3C1A2B4C2A3B1C3A4B2C4
這道題是 DFS 回溯求漢密爾頓路徑的經典範例,小規模棋盤讓暴力搜尋成為可行且最簡單的方案,關鍵在於正確處理字典序與輸出格式。