首页 > 其他分享 >bfs + bitmask

bfs + bitmask

时间:2022-10-23 12:44:26浏览次数:41  
标签:int graph length bfs keys bitmask grid new

864. Shortest Path to Get All Keys

You are given an m x n grid grid where:

  • '.' is an empty cell.
  • '#' is a wall.
  • '@' is the starting point.
  • Lowercase letters represent keys.
  • Uppercase letters represent locks.

You start at the starting point and one move consists of walking one space in one of the four cardinal directions. You cannot walk outside the grid, or walk into a wall.

If you walk over a key, you can pick it up and you cannot walk over a lock unless you have its corresponding key.

For some 1 <= k <= 6, there is exactly one lowercase and one uppercase letter of the first k letters of the English alphabet in the grid. This means that there is exactly one key for each lock, and one lock for each key; and also that the letters used to represent the keys and locks were chosen in the same order as the English alphabet.

Return the lowest number of moves to acquire all keys. If it is impossible, return -1.

Example 1:

Input: grid = ["@.a..","###.#","b.A.B"]
Output: 8
Explanation: Note that the goal is to obtain all the keys not to open all the locks.

Example 2:

Input: grid = ["@..aA","..B#.","....b"]
Output: 6

Example 3:

Input: grid = ["@Aa"]
Output: -1

Constraints:

  • m == grid.length
  • n == grid[i].length
  • 1 <= m, n <= 30
  • grid[i][j] is either an English letter, '.''#', or '@'.
  • The number of keys in the grid is in the range [1, 6].
  • Each key in the grid is unique.
  • Each key in the grid has a matching lock.
class Solution {
    /*
    关键点:
    1.图中的点可以重复访问,因为拿到的钥匙状态不同,说不定可以解锁之前不能去的节点
    2.但是同一个点在同样的钥匙状态下不能重复访问
    3.使用bitmask 来记录钥匙的状态
    4.巧妙使用了java新特性record,可以简化程序实现
    */
    record State(int keys, int i, int j) {}
    public int shortestPathAllKeys(String[] grid) {
        int x = -1, y = -1, m = grid.length, n = grid[0].length(), max = -1;
        //1.拿到起点
        //2.拿到钥匙的数量
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                char c = grid[i].charAt(j);
                if (c == '@') {
                    x = i;
                    y = j;
                }
                if (c >= 'a' && c <= 'f') {
                    max = Math.max(c - 'a' + 1, max);
                }
            }
        }
        //下面开始bfs
        State start = new State(0, x, y);
        Queue<State> q = new LinkedList<>();
        //记录已经访问过的点
        Set<State> visited = new HashSet<>();
        //从起点开始进行bfs
        visited.add(start);
        q.offer(start);
        int[][] dirs = new int[][]{{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
        int step = 0;
        while (!q.isEmpty()) {
            int size = q.size();
            while (size-- > 0) {
                State cur = q.poll();
                //11111  各位都为1,说明所有的锁都解了
                if (cur.keys == (1 << max) - 1) {
                    return step;
                }
                //遍历4个方向
                for (int[] dir : dirs) {
                    int i = cur.i + dir[0];
                    int j = cur.j + dir[1];
                    //当前拿到钥匙的状态
                    int keys = cur.keys;
                    //如果在界内的话
                    if (i >= 0 && i < m && j >= 0 && j < n) {
                        char c = grid[i].charAt(j);
                        //如果是wall,直接跳过
                        if (c == '#') {
                            continue;
                        }
                        //如果是钥匙,那么将这把钥匙所在bit位置为1
                        if (c >= 'a' && c <= 'f') {
                            keys |= 1 << (c - 'a');
                        }
                        //如果是锁,但是对应的钥匙还未找到的话,只能跳过
                        if (c >= 'A' && c <= 'F' && ((keys >> (c - 'A')) & 1) == 0) {
                            continue;
                        }
                        //判定这个位置在相同钥匙状态下是否已经访问过,如果是,那么可以跳过,
                        State s = new State(keys, i, j);
                        if (!visited.contains(s)) {
                            visited.add(s);
                            q.offer(s);
                        }
                    }
                }
            }
            step++;
        }
        return -1;
    }
}
847. Shortest Path Visiting All Nodes Hard

You have an undirected, connected graph of n nodes labeled from 0 to n - 1. You are given an array graph where graph[i] is a list of all the nodes connected with node i by an edge.

Return the length of the shortest path that visits every node. You may start and stop at any node, you may revisit nodes multiple times, and you may reuse edges.

 

Example 1:

Input: graph = [[1,2,3],[0],[0],[0]]
Output: 4
Explanation: One possible path is [1,0,2,0,3]

Example 2:

Input: graph = [[1],[0,2,4],[1,3,4],[2],[1,2]]
Output: 4
Explanation: One possible path is [0,1,4,2,3]

 

Constraints:

  • n == graph.length
  • 1 <= n <= 12
  • 0 <= graph[i].length < n
  • graph[i] does not contain i.
  • If graph[a] contains b, then graph[b] contains a.
  • The input graph is always connected.
class Solution {
    //mask:经过的节点集,bit位=1表示已经访问过  pos:节点编号
    record Node(int mask, int pos){}
    public int shortestPathLength(int[][] graph) {
        Set<Node> visited = new HashSet();
        Queue<Node> queue = new LinkedList();
        //将所有节点都作为初始节点放入queue
        for(int i = 0; i < graph.length; i++){
            Node node = new Node(1 << i, i);
            queue.offer(node);
            visited.add(node);
        }
        int step = 0;
        //当所有bit位都为1时,代表已经访问完毕所有点
        int FINISH = (1 << graph.length) - 1;
        while(!queue.isEmpty()){
            int size = queue.size();
            for(int i = 0; i < size; i++){
                Node curr = queue.poll();
                if(curr.mask == FINISH) return step;
                for(int other : graph[curr.pos]){
                    Node next = new Node(1 << other | curr.mask, other);
                    if(visited.contains(next)) continue;
                    queue.offer(next);
                    visited.add(next);
                }
            }
            step++;
        }
        return -1;
    }
}

 

标签:int,graph,length,bfs,keys,bitmask,grid,new
From: https://www.cnblogs.com/cynrjy/p/16818349.html

相关文章

  • 八数码难题——BFS
    原题链接:https://www.acwing.com/problem/content/847/通常情况下很难看出这是一道BFS题或者说看不出怎么表示状态,毕竟它的状态涉及到整个矩阵但是可以用一种unordered_......
  • Snowy Mountain (找规律来贪心+ 多源特殊bfs+根号n)
    题目大意:给定一棵 nn 个点的树,其中每个点可能是黑色或白色。一个点的高度定义为其距离最近黑色节点的距离。你初始在 ii 号节点上,势能为 00,可以做以下两种操作:......
  • UESTC 482 Charitable Exchange(优先队列+bfs)
    CharitableExchangeTimeLimit:4000/2000MS(Java/Others)   MemoryLimit:65535/65535KB(Java/Others)Submit StatusHaveyoueverheardastarcharityshow......
  • HDU 1885 Key Task(BFS)
    KeyTaskTimeLimit:3000/1000MS(Java/Others)    MemoryLimit:32768/32768K(Java/Others)TotalSubmission(s):1809    AcceptedSubmission(s):770Pr......
  • Leetcode 117 -- 树&&bfs
    题目描述填充每个节点的下一个节点题目要求我们填充每个节点的\(next\)指针,让它指向它的(同一层)右侧的节点,如果没有,指向$NULL,(初始时全部指向\(NULL\))。思路看到......
  • POJ 2227 The Wedding Juicer(三维接雨水 BFS 贪心
    POJ2227TheWeddingJuicer(三维接雨水BFS贪心)题意:​ 给出一个二维地图,其各点上权值为其高度。如果向其中填水,请问在这张地图中可以积得多少水。​ 地图长宽为300,高......
  • POJ 3697 USTC campus network(BFS 删边)
    POJ3697USTCcampusnetwork(BFS删边)题意:​ 有一张图,每个点\(n\le10000\)之间都有一条边。现在删去若干条边\(m\le1000000\),请问还有多少点是联通的。思路:​ 我......
  • POJ 2110 Mountain Walking(二分 枚举 BFS)
    POJ2110MountainWalking(二分枚举BFS)题目:​ 给出一张\(n*n(n\le100)\)的地图,每个点都有一个点权\((val\le110)\),可以任意选择路径,请问从(1,1)走到(n,n)的路......
  • 0-1 bfs 学习笔记
    01bfs是一种可以在\(\mathcal{O}(n+m)\)时间求解只含有\(0\),\(1\)两种边权的单源最短路的算法。这种情形下效率比dijkstra更高,和dijkstra一样好写(甚至更好写一......
  • 哥大周赛题目 0-1 Tree (BFS + 并查集)
    上周本地比赛,老wf选手都退役了,只剩我们这些22届本科升研究生来参赛了题目不是很难,11题,比之前的训练赛要简单很多,开场A了4题签到+1裸dp+1做过+1xjb乱搞。结果最后一......