UVa 10384 The Wall Pusher IDA* iteration plus A*

Question link: The Wall Pusher
title description:

Given a grid and the starting location of the task, your task is to find a path to get out of the grid. There may be walls around the grid. If there are walls around and there is only one continuous wall in that direction, you can push the If you block a wall, the wall will move a distance along the direction, but if there are two or more consecutive walls in the direction, it cannot move in the direction (you cannot remove the edge wall from the grid). It is guaranteed that there is a set of solutions for the input and any set of solutions is output.
Solution:
This question can use IDA ∗ IDA*IDA A ∗ A* A can use Manhattan distance as the evaluation function, and the search process is not difficult.

Code:

#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;
}

Guess you like

Origin blog.csdn.net/qq_45523675/article/details/129453927