1. 程式人生 > 實用技巧 >【LeetCode-DFS】機器人的運動範圍

【LeetCode-DFS】機器人的運動範圍

題目描述

地上有一個m行n列的方格,從座標 [0,0] 到座標 [m-1,n-1] 。一個機器人從座標 [0, 0] 的格子開始移動,它每次可以向左、右、上、下移動一格(不能移動到方格外),也不能進入行座標和列座標的數位之和大於k的格子。例如,當k為18時,機器人能夠進入方格 [35, 37] ,因為3+5+3+7=18。但它不能進入方格 [35, 38],因為3+5+3+8=19。請問該機器人能夠到達多少個格子?
示例:

輸入:m = 2, n = 3, k = 1
輸出:3

輸入:m = 3, n = 1, k = 0
輸出:1

說明:

  • 1 <= n,m <= 100
  • 0 <= k <= 20
  • 該題是《劍指Offer》的第 13 題;

題目連結: https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof/

思路

使用 dfs 來做。首先建立一個 m x n 的棋盤,然後從(0, 0)開始 dfs,如果當前位置沒有超過邊界並且當前位置的數位相加小於等於 k 並且當前位置沒有被訪問過,則進入下一層 dfs。程式碼如下:

class Solution {
public:
    int movingCount(int m, int n, int k) {
        if(k<0) return 0;
        if(k==0) return 1;

        vector<vector<int>> board(m, vector<int>(n, 0));
        board[0][0] = 1;  // 別忘了這一步
        dfs(board, 0, 0, k);

        int cnt = 0;
        for(int i=0; i<m; i++){  // 統計為 1 的格子個數
            for(int j=0; j<n; j++){
                if(board[i][j]==1) cnt++;
            }
        }
        return cnt;
    }

    void dfs(vector<vector<int>>& board, int r, int c, int& k){
        for(int i=0; i<4; i++){
            int nr = r + dirs[i][0];
            int nc = c + dirs[i][1];
            if(nr>=0 && nr<board.size() && nc>=0 && nc<board[0].size() && board[nr][nc]!=1){
                int t = nr, sum = 0;
                while(t){
                    sum += t%10;
                    t /= 10;
                }
                t = nc;
                while(t){
                    sum += t%10;
                    t /= 10;
                }
                if(sum<=k){
                    board[nr][nc] = 1;  // 置為 1 表示訪問過
                    dfs(board, nr, nc, k);
                }
            }
        }
    }

private:
    int dirs[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};
};

遞迴和回溯的區別:回溯要進行其他選擇,所以遞迴完畢要把狀態置為遞迴前的狀態,而這一題就是看機器人能走到哪裡,所以不用重置棋盤。