劍指 Offer 13. 機器人的運動範圍

有夢想的coder發表於2020-11-17

地上有一個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。請問該機器人能夠到達多少個格子?

示例 1:

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

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

1 <= n,m <= 100
0 <= k <= 20

方法:DFS + 回溯演算法。回溯演算法可以看作暴力解法的升級版,它從解決問題每一步的所有可能選項裡系統地選出一個可行的解決方案。回溯法非常適合解決由多個步驟組成的問題,而且每個步驟都有多個選項。回溯法一般用遞迴來實現。
先放C++程式碼,思路清晰明瞭。

class Solution {
public:
    int movingCount(int m, int n, int k) {
        if(k == 0) return 1;
        vector<vector<bool> > valid(m, vector<bool>(n, true)); // 記錄該位置是否被訪問過
        return dfs(valid, m, n, 0, 0, k);
    }
    int dfs(vector<vector<bool> >& valid, int m, int n, int row, int col, int k) // valid的傳值一定要用 & !!!
    {
        int sum = getSum(row) + getSum(col);
        // 如果越界,或者和大於k,或者已被訪問過了,返回0
        if(row>=m || col>=n || sum>k || !valid[row][col]) return 0;
        valid[row][col] = false; // 該位置狀態變為:已訪問過
        return 1 + dfs(valid,m,n,row+1,col,k) + dfs(valid,m,n,row,col+1,k); // 回溯法(遞迴)
    }
    int getSum(int num)
    {
        // 求某個數字所有位數相加的和
        if(num < 10) return num;
        int sum = 0;
        while(num > 0)
        {
            sum += num % 10;
            num /= 10;
        }
        return sum;
    }
};

相關文章