UVa 10384 The Wall Pusher 推墙者 IDA* 迭代加A*

题目链接: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;
}

猜你喜欢

转载自blog.csdn.net/qq_45523675/article/details/129453927
今日推荐