zoukankan      html  css  js  c++  java
  • Stealing Harry Potter's Precious

    传送门
    给出一个起点,4个终点,要求从起点出发,每个终点都走到的最短距离

    一般来说,如果只有一个终点,那么就直接bfs,但是有4个终点,用状压dp

    设置一个vis[N][N][1 << 4]来设置记录

    且每一个点存4个变量,x,y,key和step,key表示当前的状压情况

    那么不断进行bfs,如果遇到终点,那么进行状压一下u.key | (1 << (s[xx][yy] - '0'))即可,同时更新key即可

    那么如果说nex.key == (1 << k) - 1,也就是说4个终点都走过了,那么就直接返回答案即可

    第一次遇到状压bfs,记录下,感觉好神奇啊,大雾

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    #include <vector>
    #include <map>
    #include <set>
    #include <cmath>
    #include <stack>
    #include <algorithm>
    #include <ctime>
    using namespace std;
    #define ll long long
    const int N = 105;
    char s[N][N];
    int dir[][2] = {1, 0, -1, 0, 0, 1, 0, -1};
    int n, m, k;
    int sx, sy;
    bool vis[N][N][1 << 4]; // 状压数组
    struct Node{
        int x, y, key, step;
    };
    bool check(int x, int y){
        if(x < 1 || x > n || y < 1 || y > m || s[x][y] == '#') return 0;
        return 1;
    }
    int bfs(){
        queue<Node> q;
        Node now;
        now.x = sx, now.y = sy;
        now.step = 0; now.key = 0;
        q.push(now);
        while(!q.empty()) {
            Node u = q.front();
            q.pop();
            for(int i = 0; i < 4; i++) {
                int xx = dir[i][0] + u.x;
                int yy = dir[i][1] + u.y;
                if(!check(xx, yy)) continue;
                Node nex;
                if(s[xx][yy] >= '0' && s[xx][yy] <= '3') { //终点,状压一下,再继承上一个点的信息
                    if(!vis[xx][yy][u.key]) {
                        vis[xx][yy][u.key | (1 << (s[xx][yy] - '0'))] = 1;
                        nex.x = xx, nex.y = yy, nex.step = u.step + 1, nex.key = u.key | (1 << (s[xx][yy] - '0'));
                        if(nex.key == (1 << k) - 1) return nex.step; // 点走完了
                        q.push(nex);
                    }
                }else { // 普通点,继承上一个点的信息
                    if(!vis[xx][yy][u.key]) {
                        vis[xx][yy][u.key] =  1;
                        nex.x = xx, nex.y = yy, nex.key = u.key, nex.step = u.step + 1;
                        q.push(nex);
                    }
                }
            }
        }
        return -1;
    }
    int main(){
        while(~scanf("%d%d", &n, &m)) {
            if(n == 0 && m == 0) break;
            bool f = 1;
            for(int i = 1; i <= n; i++) scanf("%s", s[i] + 1);
            for(int i = 1; i <= n; i++) {
                for(int j = 1; j <= m; j++){
                    if(s[i][j] == '@') sx = i, sy = j; // 起点
                }
            }
            memset(vis, 0, sizeof(vis));
            scanf("%d", &k);
            for(int i = 0; i < k; i++) {
                int x, y;
                scanf("%d%d", &x, &y);
                if(s[x][y] == '#') f = 0;
                else if(s[x][y] == '@') {  // 把所有的终点设置为相应的数字,方便进行状压
                    s[x][y] = i + '0';
                    vis[x][y][1 << i] = 1;
                } else s[x][y] = i + '0';
            }
            if(!f) printf("-1
    ");
            else {
                printf("%d
    ", bfs());
            }
        }
        return 0;
    }
    
  • 相关阅读:
    gulp通过http-proxy-middleware开启反向代理,实现跨域
    一些我常用的css 或者 js
    四舍五入
    生成 SSH 公钥
    对象转为数组 用lodash
    廖雪峰的官方网站
    window对象
    字符串
    简单得日期
    LeetCode 113. Path Sum II 20170705 部分之前做了没写的题目
  • 原文地址:https://www.cnblogs.com/Emcikem/p/13675425.html
Copyright © 2011-2022 走看看