給定 N×N (N<9) 棋盤,0 為可通行,1 為障礙。Lele 可能被放在任意一個 0 格。需找一個最短指令序列(由 north/east/south/west 組成),使得無論起始位置為何,按序執行指令(遇障礙或邊界忽略該指令)最終都能走到邊界(即逃脫)。若有多解,輸出字典序最小者。
depth + h > limit 直接回溯。east, north, south, west 顺序嘗試方向(題目要求字典序最小)。#include <bits/stdc++.h>
using namespace std;
const int dx[4] = {0, -1, 1, 0}; // east, north, south, west
const int dy[4] = {1, 0, 0, -1};
const char* dirName[4] = {"east", "north", "south", "west"};
int N, limit;
uint64_t startMask, goalMask; // 用 64 位整數表示位置集合 (N≤8 → 64 格)
int dist[8][8]; // 每格到最近邊界的曼哈頓距離
int heuristic(uint64_t mask) {
int h = 0;
for (int i = 0; i < N; ++i)
for (int j = 0; j < N; ++j)
if (mask & (1ULL << (i*N + j)))
h = max(h, dist[i][j]);
return h;
}
bool dfs(uint64_t mask, int depth, int lastDir) {
int h = heuristic(mask);
if (h == 0) return true; // 所有位置已在邊界
if (depth + h > limit) return false;
for (int d = 0; d < 4; ++d) {
if (d == (lastDir ^ 1)) continue; // 簡單逆操作剪枝:0↔1, 2↔3
uint64_t next = 0;
for (int i = 0; i < N; ++i)
for (int j = 0; j < N; ++j)
if (mask & (1ULL << (i*N + j))) {
int ni = i + dx[d], nj = j + dy[d];
if (ni < 0 || ni >= N || nj < 0 || nj >= N || board[ni][nj] == '1') {
next |= 1ULL << (i*N + j); // 撞牆/障礙,原地不动
} else {
next |= 1ULL << (ni*N + nj);
}
}
if (dfs(next, depth + 1, d)) {
path[depth] = d;
return true;
}
}
return false;
}
int main() {
while (cin >> N) {
// 讀棋盤,計算 startMask、dist、goalMask
// 迭代加深
for (limit = heuristic(startMask); ; ++limit) {
if (dfs(startMask, 0, -1)) break;
}
// 輸出 path[0..limit-1] 對應的方向名
}
}
uint64_t 位掩碼,位運算極快。east, north, south, west,IDA* 首次找到的解即為字典序最小。本題是多智能體同步規劃的經典 IDA* 應用。關鍵在於將「所有可能位置」作為單一狀態、設計可接受的啟發函數(最大距離)、以及位掩碼加速狀態轉移。N<8 保證狀態空間可控,迭代加深找到最短解並天然保證字典序最小。