机器人的运动范围
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;
}
}
```