首页 > 试题广场 >

机器人的运动范围

[编程题]机器人的运动范围
  • 热度指数:463576 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 64M,其他语言128M
  • 算法知识视频讲解
地上有一个 rows 行和 cols 列的方格。坐标从 [0,0] 到 [rows-1,cols-1] 。一个机器人从坐标 [0,0] 的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于 threshold 的格子。 例如,当 threshold 为 18 时,机器人能够进入方格   [35,37] ,因为 3+5+3+7 = 18。但是,它不能进入方格 [35,38] ,因为 3+5+3+8 = 19 。请问该机器人能够达到多少个格子?

数据范围:

进阶:空间复杂度 ,时间复杂度
示例1

输入

1,2,3

输出

3
示例2

输入

0,1,3

输出

1
示例3

输入

10,1,100

输出

29

说明

[0,0],[0,1],[0,2],[0,3],[0,4],[0,5],[0,6],[0,7],[0,8],[0,9],[0,10],[0,11],[0,12],[0,13],[0,14],[0,15],[0,16],[0,17],[0,18],[0,19],[0,20],[0,21],[0,22],[0,23],[0,24],[0,25],[0,26],[0,27],[0,28] 这29种,后面的[0,29],[0,30]以及[0,31]等等是无法到达的      
示例4

输入

5,10,10

输出

21
推荐
public class Solution {

	public int movingCount(int threshold, int rows, int cols) {
		int flag[][] = new int[rows][cols]; //记录是否已经走过
		return helper(0, 0, rows, cols, flag, threshold);
	}

	private int helper(int i, int j, int rows, int cols, int[][] flag, int threshold) {
		if (i < 0 || i >= rows || j < 0 || j >= cols || numSum(i) + numSum(j)  > threshold || flag[i][j] == 1) return 0;		
		flag[i][j] = 1;
		return helper(i - 1, j, rows, cols, flag, threshold)
            + helper(i + 1, j, rows, cols, flag, threshold)
			+ helper(i, j - 1, rows, cols, flag, threshold) 
            + helper(i, j + 1, rows, cols, flag, threshold) 
            + 1;
	}

	private int numSum(int i) {
		int sum = 0;
		do{
			sum += i%10;
		}while((i = i/10) > 0);
		return sum;
	}
}

编辑于 2021-07-06 10:49:06 回复(81)
# -*- coding:utf-8 -*-
class Solution:
    def __init__(self):
        self.count = 0 
    def movingCount(self, threshold, rows, cols):
        # write code here
        
        vis = [[0 for i in range(cols)] for j in range(rows)]
        self.dfs(0,0,rows,cols,vis,threshold)
                
        return self.count
    def dfs(self,i,j,rows,cols,vis,threshold):
        if i <0 or j<0 or i>=rows or j>=cols or vis[i][j]:
            return 
        if  self.num(i)+self.num(j) >threshold:
            return 
        self.count +=1
        vis[i][j] = 1
        self.dfs(i-1, j, rows, cols, vis, threshold)
        self.dfs(i+1, j, rows, cols, vis, threshold)
        self.dfs(i, j-1, rows, cols, vis, threshold)
        self.dfs(i, j+1, rows, cols, vis, threshold)
    def num(self,n):
        s = 0
        while n >0:
            s += n % 10
            n = n//10
        return s
发表于 2021-05-13 14:50:19 回复(0)
# -*- coding:utf-8 -*-
class Solution:
    def getSum(self,x,y):
        sum = 0
        for a in [x,y]:
            while a // 10 != 0:
                sum += a%10
                a = a//10
            sum += a
        return sum
    def if_going(self, x,y):
        return (0<=x<=self.rows-1 and 0<=y<=self.cols-1 and (x,y) not in self.visited
               and self.getSum(x, y)<=self.threshold)
    def movingCountCore(self, x,y):
        count = 0
        if self.if_going(x, y):
            self.visited[(x,y)] = True
            count = 1+self.movingCountCore(x-1,y)+self.movingCountCore(x+1,y)+\
            self.movingCountCore(x,y+1)+self.movingCountCore(x,y-1)
        return count
    def movingCount(self, threshold, rows, cols):
        assert rows>=0 and cols >=0
        self.threshold = threshold
        self.visited = {}
        self.rows = rows
        self.cols = cols
        return self.movingCountCore(0, 0)

发表于 2021-04-15 22:35:12 回复(1)
# -*- coding:utf-8 -*-
class Solution:
    def movingCount(self, threshold, rows, cols):
        # write code here
        self.threshold = threshold
        self.rows, self.cols = rows, cols
        self.dict = {}
        self.dfs(0, 0)
        return len(self.dict)
        
    def get_sum(self, i, j):
        num = 0
        while i:
            temp = i%10
            i //= 10
            num += temp
        while j:
            temp = j%10
            j //= 10
            num += temp
        return num
    
    def dfs(self, i, j):
        if i>=self.rows&nbs***bsp;j>=self.cols:   # 越界
            return 
        if self.get_sum(i, j)>self.threshold:   # 超过阈值
            return
        if self.dict.get((i,j)):   # 规避重复路径
            return
        self.dict[(i,j)] = 1   # 走过了就添加key
        self.dfs(i+1, j)   # 因为我们是从0,0开始,所有只需要走下、右即可
        self.dfs(i, j+1)

发表于 2021-03-17 11:36:33 回复(0)

python解法:

# -*- coding:utf-8 -*-
'''
解法:可以用dfs或者bfs做,不会,树等最后再做;
'''
class Solution:
    def getsum(self,num):
            sum = 0
            while num > 0:
                sum += num % 10
                num /= 10
            return sum
    def movingCount(self, threshold, rows, cols):
        count = 0
        for i in range(rows):
            for j in range(cols):
                if self.getsum(i) + self.getsum(j) <= threshold:
                    count += 1
                # emmm,但是这代码作何解释呢?
                elif rows == 1 or cols == 1:
                    return count
        return count
编辑于 2021-02-19 13:25:36 回复(0)
# -*- coding:utf-8 -*-
class Solution:
    def movingCount(self, threshold, rows, cols):
        moving = []
        for m in range(rows):
            for n in range(cols):
                if sum(map(int, list(str(m)+str(n)))) <= threshold:
                    if m == 0 and n == 0 or (m-1,n) in moving or (m+1,n) in moving or (m,n-1) in moving or (m,n+1) in moving:
                        moving.append((m, n))
        return len(moving)
发表于 2020-08-12 14:23:17 回复(0)
# -*- coding:utf-8 -*-
class Solution:
    def movingCount(self, threshold, rows, cols):
        # write code here
        t = 0
        #注意别把range(rows)写成rows!!!
        for i in range(rows):
            for j in range(cols):
                if self.calSum(i) + self.calSum(j)<= threshold:
                    t += 1
                #当只有一行一列时,直接结束遍历
                elif (rows==1&nbs***bsp;cols==1):
                    return t 
        return t
        
    def calSum(self,num):
        sum = 0
        while num :
            sum += num % 10
            num = num // 10
        return sum
    

发表于 2020-08-04 12:46:49 回复(0)

BFS遍历地图,找到从(0,0)开始的所有满足条件的可达点。
[!] 注意考虑k<0的情况,这种情况下(0,0)都不可达。

# -*- coding:utf-8 -*-
class Solution:
    def check(self, x, y, k):
        res = 0
        while x!=0 or y!=0:
            res += x%10
            x //= 10
            res += y%10
            y //= 10
        return res<=k
    def movingCount(self, threshold, rows, cols):
        # write code here
        #BFS
        pos = [(0, 0)]
        flag = [[0 for i in range(cols)] for j in range(rows)]  # 判断是否走过
        if threshold < 0:
            return 0
        cnt = 1
        flag[0][0] = 1
        while len(pos)!=0:
            x, y = pos[0]
            del(pos[0])
            if y+1<cols and flag[x][y+1]==0 and self.check(x, y+1, threshold):
                pos.append((x, y+1))
                flag[x][y+1] = 1
                cnt += 1
            if y-1>=0 and flag[x][y-1]==0 and self.check(x, y-1, threshold):
                pos.append((x, y-1))
                flag[x][y-1] = 1
                cnt += 1
            if x+1<rows and flag[x+1][y]==0 and self.check(x+1, y, threshold):
                pos.append((x+1, y))
                flag[x+1][y] = 1
                cnt += 1
            if x-1>=0 and flag[x-1][y]==0 and self.check(x-1, y, threshold):
                pos.append((x-1, y))
                flag[x-1][y] = 1
                cnt += 1
        return cnt
发表于 2020-08-04 09:32:49 回复(0)
class Solution:
    def movingCount(self, k, m, n):
        q = []
        s = set()
        q.append((0, 0))
        while len(q) > 0:
            x, y = q.pop(0)
            if not (x, y) in s and 0 <= x < m and 0 <= y < n \
                    and sum(map(int, str(x))) + sum(map(int, str(y))) <= k:
                s.add((x, y))
                for nx, ny in [(x + 1, y), (x, y + 1)]:
                    q.append((nx, ny))
        return len(s)

编辑于 2020-04-13 00:36:25 回复(0)
#思路与回溯法的矩阵路径相似,值得注意的是visited储存的是每个位置是否已经被检查过。不加visited的话,会导致重复出现。
class Solution:
    def movingCount(self, threshold, rows, cols):
        # write code here
        if threshold<=0 or rows<=0 or cols<=0:
            return 0
        visited=[False]*rows*cols
        count=self.movingCountCore(threshold,rows,cols,0,0,visited)
        return count
    def movingCountCore(self,threshold,rows,cols,row,col,visited):
        count=0
        if self.check(threshold,rows,cols,row,col,visited):
            visited[row*cols+col]=True
            count=1+self.movingCountCore(threshold,rows,cols,row-1,col,visited)+self.movingCountCore(threshold,rows,cols,row+1,col,visited)+self.movingCountCore(threshold,rows,cols,row,col-1,visited)+self.movingCountCore(threshold,rows,cols,row,col+1,visited)
        return count
    def check(self,threshold,rows,cols,row,col,visited):
        if row>=0 and row<rows and col>=0 and col<cols and self.getDigitSum(row)+self.getDigitSum(col)<=threshold and (not visited[row*cols+col]):
            return True
        return False
    def getDigitSum(self,row):
        sum=0
        while row>0:
            sum+=row%10
            row/=10
        return sum
发表于 2020-03-16 14:41:26 回复(0)
# -*- coding:utf-8 -*-
class Solution:
    def movingCount(self, threshold, rows, cols):
        # 计算每一位之和
        def getsum(num):
            sum = 0
            while num>0:
                sum += num%10
                num = num//10
            return sum
        path = []
        def back(start):
            if start in path or getsum(start[0]) + getsum(start[1])> threshold:
                return None
            if start[0]>=rows or start[1]>=cols:
                return None
            path.append(start)       # 从0,0开始向右向下遍历,减少走回头路的次数             
            back([start[0]+1,start[1]])
            back([start[0],start[1]+1])
        back([0,0])
        return len(path) 
           


编辑于 2020-03-09 12:45:41 回复(0)
class Solution:
    def movingCount(self, threshold, rows, cols):
        matrix = [[0 for i in range(cols)] for j in range(rows)]
        def numberCount(m):
            n = 0
            while m:
                n += m%10
                m = m//10
            return n
        matrix[0][0] = 1
        if threshold <= 0:
            return 0
        else:
            for i in range(rows):
                for j in range(cols):
                    if numberCount(i) + numberCount(j) <= threshold and (matrix[i][j-1]==1&nbs***bsp;matrix[i-1][j]==1):
                        matrix[i][j] = 1
        return sum(map(sum,matrix))

发表于 2020-03-08 23:23:17 回复(0)
# -*- coding:utf-8 -*-
class Solution:
    def movingCount(self, threshold, rows, cols):
        x = [[0 for _ in range(cols)] for _ in range(rows)]
        self.check_cell(threshold, 0, 0,rows,cols,x)
        
        res = 0
        for i in range(rows):
            res += sum(x[i])
        return res
    
    def check_cell(self, k, i, j,rows,cols,x):
        if self.check_sum(k,i,j):
            x[i][j] = 1
            if i > 0 and x[i-1][j] == 0 and self.check_sum(k,i-1,j):
                self.check_cell(k,i-1,j,rows,cols,x)
            if i < rows -1 and x[i+1][j] == 0 and self.check_sum(k,i+1,j):
                self.check_cell(k,i+1,j,rows,cols,x)
            if j > 0  and x[i][j-1] == 0 and self.check_sum(k,i,j-1):
                self.check_cell(k,i,j-1,rows,cols,x)
            if j < cols -1 and x[i][j+1] == 0 and self.check_sum(k,i,j+1):
                self.check_cell(k,i,j+1,rows,cols,x)
    def check_sum(self,k,i,j):
        row_sum = 0
        col_cum = 0
        while i != 0 :
            row_sum += i % 10
            i //= 10
        while j != 0:
            col_cum += j % 10
            j //= 10
        if row_sum + col_cum <= k:
            return True
        return False
    

发表于 2020-02-26 23:45:15 回复(0)
# -*- coding:utf-8 -*-
class Solution:
    def movingCount(self, threshold, rows, cols):
        # write code here
        if threshold<0&nbs***bsp;rows<1&nbs***bsp;cols<1:
            return 0
        #用来表示该格子是否被走过
        visited=[0 for i in range(rows*cols)]
        #从(0,0)起点,开始走起
        count1=self.movingCountcore(threshold, rows, cols,0,0,visited)
        return count1
    def movingCountcore(self, threshold, rows, cols,row,col,visited):
        count1=0
        if self.checkcore(threshold,rows,cols,row,col,visited):
            #首先检验该格子是否符合条件
            visited[row*cols+col]=1
            #递归方法的一个简单应用,求总体的行走轨迹,只需要现在的占据的格子,加上在四个方向上的行走轨迹
            count1=1+self.movingCountcore(threshold, rows, cols,row,col-1,visited) \
              +self.movingCountcore(threshold, rows, cols,row,col+1,visited) \
              +self.movingCountcore(threshold, rows, cols,row-1,col,visited) \
              +self.movingCountcore(threshold, rows, cols,row+1,col,visited)
        return count1
    def checkcore(self,threshold,rows,cols,row,col,visited):
        if row>=0 and row<rows and col>=0 and col<cols and self.numbercount(row)+self.numbercount(col)<=threshold and not visited[row*cols+col]:
            return True
        return False
    def numbercount(self,number):
        sumnum=0
        while(number>0):
            sumnum+=number%10
            number=number/10
        return sumnum

递归方法的一个简单应用,求总体的行走轨迹,只需要现在的占据的格子,加上在四个方向上的行走轨迹
发表于 2020-02-17 21:23:57 回复(0)
Python广度优先搜索,非递归。以左上为原点,纵轴为x,横轴为y。
# -*- coding:utf-8 -*-
class Solution:
    def movingCount(self, threshold, rows, cols):
        # write code here
        past = {}
        queue = [(0, 0)]
        cnt = 0
        while queue:
            x, y = queue.pop(0)
            if (x, y) not in past and sum([int(s) for s in str(x)+str(y)]) <= threshold:
                cnt += 1
                past[(x, y)] = 1
                if x <= rows-2:
                    queue.append((x+1, y))
                if y <= cols-2:
                    queue.append((x, y+1))
        return cnt


编辑于 2020-02-14 16:22:29 回复(0)
# -*- coding:utf-8 -*-
# 解题思路:深度优先搜索,一个格子的准入条件为下标不越界;并且各位数之和不超出给定的值;并且没有被进入过
# 从(0,0)开始计算可以进入的格子的个数为每个格子4个方向上可以进入的格子数+1;
# 为保证格子不能被重复进入,使用visited数组记录格子是否被进入过
class Solution:
    def movingCount(self, threshold, rows, cols):
        # write code here
        if rows < 0&nbs***bsp;cols < 0&nbs***bsp;threshold < 0:
            return 0

        visited = [[False for j in range(cols)] for i in range(rows)]

        def compute_sum(row, col):
            sum = 0

            while row:
                sum += row % 10
                row = row // 10

            while col:
                sum += col % 10
                col = col // 10

            return sum

        def canInter(row, col):
            if 0 <= row < rows and 0 <= col < cols and compute_sum(row, col) <= threshold and not visited[row][col]:
                return True

            return False

        def compute_count(row, col):
            count = 0

            if canInter(row, col):
                visited[row][col] = True
                count = 1 + compute_count(row - 1, col) + compute_count(row, col + 1) + compute_count(row + 1, col) \
                        + compute_count(row, col - 1)

            return count

        return compute_count(0, 0)
    

发表于 2020-01-21 21:45:41 回复(0)
用bfs广度优先,初始化一个全为0的二维数组,用bfs判断能进入则值改为1,最后统计1的总个数
# -*- coding:utf-8 -*-
class Solution:
    def movingCount(self, threshold, rows, cols):
        m=[]
        for i in range(rows):
            m.append([0]*cols)
        if threshold>=0:
            m[0][0]=1
        d=[(1,0),(-1,0),(0,1),(0,-1)]
        t=[(0,0)]
        def fit(x,y):
            s=str(x)+str(y)
            res=0
            for i in s:
                res+=int(i)
            return res<=threshold
        while t:
            x,y=t.pop(0)
            for dx,dy in d:
                if 0<=x+dx<rows and 0<=y+dy<cols and m[x+dx][y+dy]==0 and fit(x+dx,y+dy):
                    m[x+dx][y+dy]=1
                    t.append((x+dx,y+dy))
        c=0
        for i in range(rows):
            for j in range(cols):
                if m[i][j]==1:
                    c+=1
        return c


发表于 2019-11-23 16:24:47 回复(0)
class Solution:
    def __init__(self):
        self.cnt=0

    def movingCount(self, threshold, rows, cols):
        matrix=[[i+j*cols for i in range(cols)]for j in range(rows)]
        self.dfs(threshold,rows,classmethod,0,0,matrix)
        return self.cnt


    def dfs(self,threshold,rows,cols,i,j,matrix):
        if self.check_valid(threshold,rows,cols,i,j,matrix):
            self.cnt+=1
            matrix[i][j]=None   # 痛苦地调了半天,发现是=写成了==号
            print(matrix)
            self.dfs(threshold,rows,cols,i,j+1,matrix)
            self.dfs(threshold,rows,cols,i,j-1,matrix)
            self.dfs(threshold,rows,cols,i-1,j,matrix)
            self.dfs(threshold,rows,cols,i+1,j,matrix)

    def check_valid(self,threshold,rows,cols,i,j,matrix):
        try:
            if matrix[i][j]!=None and self.get_digit_sum(i,j)<=threshold:return True
            else:return False
        except:  # 这种情况是数组越界,用try catch写起来很简单
            return False

    def get_digit_sum(self,i,j):
        return reduce(lambda x,y:x+y,map(lambda x:int(x),str(i)+str(j))) # 求数位和一行搞定爽不爽
发表于 2019-08-20 20:02:43 回复(0)
完结撒花。刷过这一遍,感觉对自己还是有帮助的
# -*- coding:utf-8 -*-
class Solution:
    def __init__(self):
        self.flag = []
        self.count = 0
    def movingCount(self, threshold, rows, cols):
        self.flag = [0]*rows*cols
        self.Mcount(threshold, rows, cols, 0, 0)
        return self.count
    def Mcount(self, threshold, rows, cols, row, col):
        if row>=rows or col>=cols:
            return
        index = row*cols+col
        if self.flag[index] == 1:
            return 
        self.flag[index] = 1
        suum = 0
        row1,col1 = row,col
        while row1!=0:
            suum += row1%10
            row1 //= 10
        while col1!=0:
            suum += col1%10
            col1 //= 10
        if suum <= threshold:
            self.count += 1
            self.Mcount(threshold, rows, cols, row, col+1)
            self.Mcount(threshold, rows, cols, row+1, col)


发表于 2019-08-10 10:56:17 回复(0)