2617. 網格圖中最少訪問的格子數(困難)

athenanevergiveup發表於2024-04-01

核心思想
比較直觀的想法就是BFS,但是每次遍歷能走的點(右走,下走)會超時
考慮用兩個set陣列,
TreeSet<Integer>[] R = new TreeSet[n]; TreeSet<Integer>[] C = new TreeSet[m];
R[i]表示第i行還剩下哪些列col沒去過,那麼遍歷就變為了二分查詢第一個比當前j大的col
col > j + grid[i][j]時break
TODO:iterator

public int minimumVisitedCells(int[][] grid) {
        // n 行 m 列
        int n = grid.length, m = grid[0].length;
        //儲存步數
        int[][] f = new int[n][m];
        // 使用雙重迴圈來填充二維陣列
        for (int i = 0; i < n; i++) {
            Arrays.fill(f[i], -1);
        }
        TreeSet<Integer>[] R =  new TreeSet[n];
        TreeSet<Integer>[] C =  new TreeSet[m];
        for(int i = 0; i < n; i++)
            R[i] = new TreeSet<Integer>();
        for(int j = 0; j < m; j++)
            C[j] = new TreeSet<Integer>();
        for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++){
                if(i + j > 0){
                    R[i].add(j);
                    C[j].add(i);
                }
            }
        }
        Queue<int[]> q = new ArrayDeque<>();
        q.offer(new int[]{0, 0});
        f[0][0] = 1;
        while(!q.isEmpty()){
            int[] tp = q.poll();
            int i = tp[0], j = tp[1];
            // 向右走 去R中找
            // 第一個大於j的數
            Integer ceil = R[i].ceiling(j);
            if(ceil != null){
                //最遠距離
                int maxiCol = j + grid[i][j];
                Iterator<Integer> iterator = R[i].tailSet(ceil).iterator();
                while(iterator.hasNext()){
                    int col = iterator.next();
                    if (col > maxiCol)
                        break;
                    //記錄步數
                    f[i][col] = f[i][j] + 1;
                    //推入佇列
                    q.offer(new int[]{i, col});
                    //移出Set
                    iterator.remove();
                    C[col].remove(i);

                }
            }
            // 向下走 去C中
            // 第一個大於i的數
            ceil = C[j].ceiling(i);
            if(ceil != null){
                //最遠距離
                int maxiRow = i + grid[i][j];
                Iterator<Integer> iterator = C[j].tailSet(ceil).iterator();
                while(iterator.hasNext()){
                    int row = iterator.next();
                    if(row > maxiRow)
                        break;
                    //記錄步數
                    f[row][j] = f[i][j] + 1;
                    //推入佇列
                    q.offer(new int[]{row, j});
                    //移出Set
                    iterator.remove();
                    R[row].remove(j);
                }
            }
        }
        return f[n-1][m-1];
    }

相關文章