Luogu P2802 回家(bfs、最优性剪枝)

P2802

思路:

普通的dfs和bfs需要打vis标记,而在这题中标记不好处理,因为可能会遇到先到一个地方加满hp再原路返回的情况。

这里我们用f数组记录(i, j)位置上的最大hp,因为到达一个点(x, y)时的hp较少的话走出来的结果不会比f[x][y]走出来的结果更优,因此我们根据这一性质进行剪枝,而不使用vis标记。

Code:
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> PI;
const int N = 60;

const int dir[4][2] = { {1,0},{-1,0},{0,1},{0,-1} };
struct Node {
    int x, y, hp, step;
};
int n, m, mp[N][N];
PI st;
int f[N][N]; //f[i][j] 表示 (i, j)位置上的最大hp
int ans = -1;

void bfs() {
    queue<Node> q;
    q.push({st.first, st.second, 6, 0});
    while (!q.empty()) {
        Node now = q.front(); q.pop();
        if (now.x < 1 || now.x > n || now.y < 1 || now.y > m) //越界
            continue;
        if (!now.hp || mp[now.x][now.y] == 0) //hp为0/障碍物
            continue;
        if (now.hp <= f[now.x][now.y]) //最优性剪枝
            continue;
        f[now.x][now.y] = now.hp;
        if (mp[now.x][now.y] == 3) {
            ans = now.step;
            return;
        }
        if (mp[now.x][now.y] == 4) {
            now.hp = 6;
        }
        for (int i = 0; i < 4; i++) {
            int dx = now.x + dir[i][0], dy = now.y + dir[i][1];
            q.push({dx, dy, now.hp - 1, now.step + 1});
        }
    }
}

int main() {
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++) {
            cin >> mp[i][j];
            if (mp[i][j] == 2) st.first = i, st.second = j;
        }
    bfs();
    cout << ans << endl;
    return 0;
}

/*
9 9
2 0 1 1 4 0 1 1 4
1 0 1 0 1 0 1 0 1
1 0 1 0 1 0 1 0 1
1 0 4 0 1 0 4 0 1
1 0 1 0 1 0 1 0 1
4 0 1 0 4 0 1 0 3
1 0 1 0 1 0 1 0 0
1 0 1 0 1 0 1 0 0
1 1 4 0 1 1 4 0 0

//ans = 45

9 9
2 4 4 4 4 4 4 4 4
4 4 4 4 4 4 4 4 4
4 4 4 4 4 4 4 4 4
4 4 4 4 4 4 4 4 4
4 4 4 4 4 4 4 4 4
4 4 4 4 4 4 4 4 4
4 4 4 4 4 4 4 4 4
4 4 4 4 4 4 4 4 4
4 4 4 4 4 4 4 4 3

//ans = 16

test 11
7 6
2 0 0 0 0 0 
1 0 0 0 0 0 
1 1 4 0 0 0 
1 0 0 0 0 0 
1 1 1 1 1 3
4 0 1 0 4 0 
0 0 4 0 0 0

//ans = 15
*/
posted @ 2021-01-26 16:47  Nepenthe8  阅读(142)  评论(0编辑  收藏  举报