UVa 10384 ウォール プッシャー IDA* 反復プラス A*

質問リンク: The Wall Pusher
タイトルの説明:

グリッドとタスクの開始位置が与えられた場合、あなたのタスクはグリッドから抜け出すための経路を見つけることです。グリッドの周囲に壁がある場合があります。周囲に壁があり、その方向に連続する壁が 1 つだけある場合は、壁をブロックすると、壁はその方向に沿って一定距離移動しますが、その方向に 2 つ以上の壁が連続している場合は、その方向に移動できません (グリッドから端の壁を削除することはできません)。入力に対して一連の解が存在し、任意の一連の解が出力されることが保証されます。
解決策:
この質問ではIDA ∗ IDA*を使用できます。IDA 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