zoukankan      html  css  js  c++  java
  • 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
    */
    
  • 相关阅读:
    c#接口和抽象类的区别(转)
    Dephi阿拉伯数字转换成英文和中文大写
    Code Rush Express Template 制作
    SQL中对学习成绩自动排名次
    Resharper上手指南
    如何實現域控制中部分用戶可以寫Programme files目錄的權限?
    阿拉伯数字转换英文数字表示算法解析及其实现
    BOM 算法
    OGRE1.7.1.1vs2008安装
    近一个月工作小总结
  • 原文地址:https://www.cnblogs.com/Nepenthe8/p/14331239.html
Copyright © 2011-2022 走看看