w×h 棋盤(w≤20, h≤20),0 空地,1 障礙,2 起點,3 終點。冰壺從起點出發,每次選一個方向投擲,直線滑動直到:
投擲方向相鄰格不能是障礙。最多 10 次投擲,求最少次數,失敗輸出 -1。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 25, INF = 0x3f3f3f3f;
int w, h, sx, sy, ex, ey, minn;
int mp[maxn][maxn];
int dir[4][2] = {{-1,0},{0,1},{1,0},{0,-1}};
bool fail;
bool inBoard(int x, int y) { return x>=0 && x=0 && y 10) return;
for (int d = 0; d < 4; d++) {
int nx = x + dir[d][0], ny = y + dir[d][1];
if (!inBoard(nx, ny) || mp[nx][ny] == 1) continue; // 相鄰是障礙或出界,不能投
// 模擬滑動
while (inBoard(nx, ny) && mp[nx][ny] != 1) {
if (mp[nx][ny] == 3) { // 到達終點
if (cnt + 1 < minn) { minn = cnt + 1; fail = false; }
return;
}
nx += dir[d][0]; ny += dir[d][1];
}
if (!inBoard(nx, ny)) continue; // 滑出界
// 撞到障礙:停在障礙前一格,障礙消失
mp[nx][ny] = 0;
dfs(nx - dir[d][0], ny - dir[d][1], cnt + 1);
mp[nx][ny] = 1; // 回溯恢復
}
}
int main() {
while (scanf("%d%d", &w, &h), w || h) {
for (int i = 0; i < h; i++)
for (int j = 0; j < w; j++) {
scanf("%d", &mp[i][j]);
if (mp[i][j] == 2) { sx = i; sy = j; }
else if (mp[i][j] == 3) { ex = i; ey = j; }
}
fail = true; minn = INF;
dfs(sx, sy, 0);
if (fail || minn > 10) printf("-1\n");
else printf("%d\n", minn);
}
return 0;
}
fail 標記是否有解