runtimegroup / puzzle

刷题

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

机器人的运动范围

cuifan1995 opened this issue · comments

地上有一个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
示例 1:

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

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

/**
 * @param {number} m
 * @param {number} n
 * @param {number} k
 * @return {number}
 */
var movingCount = function(m, n, k) {
    let arr = [];
    function func(x, y, k, arr) {
        if(x < 0 || y < 0 || x > m-1 || y > n-1 || sum(x) + sum(y) > k || arr[n * x + y]) return;
        arr[n * x + y] = true;
        func(x - 1, y, k, arr);
        func(x + 1, y, k, arr);
        func(x, y - 1, k, arr);
        func(x, y + 1, k, arr);
    }
    func(0, 0, k, arr);
    return arr.filter(item=>!!item).length;
};

function sum(n) {
    return parseInt(n / 100) + parseInt(n / 10 % 10) + n % 10
}

var movingCount = function(m, n, k) {
    var count = 0,arr = [];
    for(var i = 0; i<= m-1; i++) {
        arr[i] = [];
        for(var j = 0; j<= n-1; j++) {
            arr[i].push({value: sum(i) + sum(j), flag: false})
        } 
    }
var check = function(i, j) {
    if(i <= m-1 && j <= n-1) {
        if(arr[i][j].value <=k && arr[i][j].flag == false) {
            count++;
            arr[i][j].flag = true;
            check(i, j+1)
            check(i+1, j)
        } 
    }
  
}
    check(0,0)
    return count;
};

var sum = function(i) {
    return Math.floor(i/100) + Math.floor(i%100/10) + Math.floor(i%100%10)
}
/**
     * @param {number} m
     * @param {number} n
     * @param {number} k
     * @return {number}
     */
    var movingCount = function(m, n, k) {
        /**
         00 01 02 03 04 05 0n
         10 11 12 13 14 15
         20
         30
         m0             m-1, n-1

         上       下      左      右
     上下左右  上下左右 上下左右 上下左右
         遍历这个树,中断条件:
         1. 超矩阵边界
         2. 该节点已被其他路踩到
         3. 不能进入行坐标和列坐标的数位之和大于k的格子
          */
        const arr = []
        let result = 0
        /**
         计算一个数的数位之和呢?
         1. js 转字符串分割单独的数相加
         2. 对数 x 每次对 10 取余,就能知道数 x 的个位数是多少,然后再将 x 除 10,这个操作等价于将 x 的十进制数向右移一位,删除个位数(类似于二进制中的 >> 右移运算符),不断重复直到 x 为 0 时结束。
         */
        function sum(x) {
            return String(x).split('').reduce(function(a, b){
                return a + Number(b)
            },0)
        }
        function sum2 (x) {
            let r = 0
            while(x) {
                r += x % 10
                x = Math.floor(x / 10)
            }

        }
        function check(x, y){
            // 1. 超矩阵边界
            if (x < 0 || y < 0 || x >= m  || y >= n ) {
                return 0
            }
            // 2. 该节点已被其他路踩到 或已知不符合
            if (arr[x][y]) return 0
            // 3. 不能进入行坐标和列坐标的数位之和大于k的格子
            if (sum(x) + sum(y) > k) {
                arr[x][y] = 1
                return 0
            }
            result += 1
            arr[x][y] = 1
            return 1
        }
        for(let i = 0; i< m;i++) {
            arr[i] = []
            for (let j = 0;j<n;j++) {
                arr[i].push(0) // 踩过为1 已知不符合也为1 没踩为0
            }
        }

        /**
         *
         * @param x 机器人当前位置
         * @param y
         * 上: x, y-1
         下: x, y+1
         左:x-1,y
         右: x+1,y
         */
        function go(a, x, y) {
            console.log(x, y)
            check(x, y)
            // a !== 2 && check(x, y - 1) && go(1, x, y - 1)
            a !== 1 && check(x, y + 1) && go(2, x, y + 1)
            // a !== 4 && check(x - 1, y) && go(3, x - 1, y)
            a !== 3 && check(x + 1, y) && go(4, x + 1, y)
        }
        go(0,0,0)
        return result
    };

    console.log(movingCount(2, 3, 1))
/**
 * 动态规划
 2.判断思路
 关键:
 能否到达某个元素,
 1.取决于该元素是否被允许到达(位数和<=k)?
 2.若被允许,它左边的元素 或 它上边的元素 至少有一个存在?
 3.若存在,是否已到达过?
 以上三个条件全满足则该元素可到达。

 利用以下判断条件,遍历整个二维数组:
 1.初始元素(0,0)一定可到达:
 直接记录为该元素已到达 并 计数;
 2.该元素可到达:
 若 { 位数和<=k 且 [ 该元素的上边元素(存在 且 已到达过) 或 该元素的左边元素(存在 且 已到达过) ] }
 则 记录为该元素已到达 并 计数;
 3.否则该元素不可到达:
 记录为该元素不可到达。

 对应代码:


 作者:elapse-4
 链接:https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof/solution/ji-qi-ren-de-yun-dong-fan-wei-shuang-bai-luo-ji-zu/
 来源:力扣(LeetCode)
 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
 */
```javascript`
for(int i=0;i<m;i++){
    for(int j=0;j<n;j++){
        //1.初始元素(0,0)一定可到达
        if(i==0&&j==0){
            v[i][j]=1;
            c++;
        }
        //2.该元素可到达
        else if(s(i)+s(j)<=k&&((i-1>=0 &&v[i-1][j]==1)||(j-1>=0&&v[i][j-1]==1))){
            v[i][j]=1;
            c++;
        }
        //3.该元素不可到达
        else
            v[i][j]=0;
    }
}
```