题目链接:The Wall Pusher
题目描述:
给定一个网格,和任务起始位置,你的任务是找到一条路径能够走出网格,网格的四周可能会存在墙壁,如果周围有墙壁并且该方向只有连续一堵墙,那么可以推动该堵墙,墙会沿着该方向移动一个距离,但是如果有改方向连续出现两堵或以上的墙则不能往改方向行进(你不能将边缘的墙移除网格)。保证输入存在一组解,输出任意一组解。
题解:
本题可以使用 I D A ∗ IDA* IDA∗, A ∗ A* A∗可以使用曼哈顿距离作为评估函数,搜索的过程也没有难度。
代码:
#include <bits/stdc++.h>
const int ROW_NUM = 4;
const int COLUMN_NUM = 6;
const int DIRECTION_NUM = 4;
const int INF = 0x3f3f3f3f;
using namespace std;
int n, m, x, y, maxDepth;
int grid[ROW_NUM][COLUMN_NUM];
int dx[] = {
1, -1, 0, 0};
int dy[] = {
0, 0, 1, -1};
char direction[] = "SNEW";
int directionNum[] = {
8, 2, 4, 1};
string ans;
vector<pair<int, int>> destination;
enum ENUM_DIRECTION
{
SOUTH,
NORTH,
EAST,
WEST,
};
bool inBound(int x, int y)
{
return x >= 0 && x < ROW_NUM && y >= 0 && y < COLUMN_NUM;
}
int minDis(int x, int y)
{
int res = INF;
for (auto ed : destination) {
res = min(res, abs(ed.first - x) + abs(ed.second - y) + 1);
}
return res;
}
bool dfs(int nowDepth, int x, int y)
{
if (nowDepth == maxDepth) {
return !inBound(x, y); }
if (nowDepth + minDis(x, y) > maxDepth) {
return false; }
for (int i = 0; i < DIRECTION_NUM; i++) {
int nx = x + dx[i];
int ny = y + dy[i];
if ((grid[x][y]&directionNum[i]) == 0) {
// 没有墙
ans.push_back(direction[i]);
if (dfs(nowDepth + 1, nx, ny)) {
return true; }
ans.pop_back();
} else if (inBound(nx, ny) && (grid[nx][ny] & directionNum[i]) == 0){
// 该方向上只有一个墙
int nnx = nx + dx[i];
int nny = ny + dy[i]; // 这里还需要考虑该方向后一个的反方向也会增加一面墙
grid[x][y] ^= directionNum[i];
grid[nx][ny] ^= directionNum[i];
if (inBound(nnx, nny)) {
grid[nnx][nny] ^= directionNum[i ^ 1]; }
ans.push_back(direction[i]);
if (dfs(nowDepth + 1, nx, ny)) {
return true; }
grid[x][y] ^= directionNum[i];
grid[nx][ny] ^= directionNum[i];
if (inBound(nnx, nny)) {
grid[nnx][nny] ^= directionNum[i ^ 1]; }
ans.pop_back();
}
}
return false;
}
int main()
{
while (cin >> x >> y && x != 0 && y != 0) {
ans = "";
destination.resize(0);
swap(x, y);
x--, y--;
for (int i = 0; i < ROW_NUM; i++) {
for (int j = 0; j < COLUMN_NUM; j++) {
cin >> grid[i][j];
// 可能会有重复的点进入vector但是这对效率的影响很低
if (i == 0 && (grid[i][j] & directionNum[NORTH]) == 0) {
destination.push_back({
i, j}); }
if (j == 0 && (grid[i][j] & directionNum[WEST]) == 0) {
destination.push_back({
i, j}); }
if (i == ROW_NUM - 1 && (grid[i][j] & directionNum[SOUTH]) == 0) {
destination.push_back({
i, j}); }
if (j == COLUMN_NUM - 1 && (grid[i][j] & directionNum[EAST]) == 0) {
destination.push_back({
i, j}); }
}
}
for (maxDepth = 0; ; maxDepth++) {
if (dfs(0, x, y)) {
cout << ans << endl;
break;
}
}
}
return 0;
}