Description
地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?
Code
一开始没注意到机器人一次只移动一格,所以写的代码是计算所有格内满足行列坐标数位之和小于等于k的格子数,算是更厉害一些吧,哈哈!
# -*- coding:utf-8 -*-
class Solution:
def movingCount(self, threshold, rows, cols):
# write code here
if threshold == 0:
return 0
index = {}
for i in range(rows):
cnt = self.cnt(i)
if cnt <= threshold:
if cnt in index:
index[cnt] += 1
else:
index[cnt] = 1
else:#去掉就是算除去一次一步条件下机器人可达的格子数
break#去掉就是算除去一次一步条件下机器人可达的格子数
res = 0
for i in range(cols):
cnt = self.cnt(i)
if threshold - cnt >= 0:
for j in index:
if j + cnt <= threshold:
res += index[j]
else:#去掉就是算除去一次一步条件下机器人可达的格子数
break;#去掉就是算除去一次一步条件下机器人可达的格子数
return res
def cnt(self, num):
res = num % 10
num /= 10
while num:
res += num % 10
num /= 10
return res
该算法的设计思路恰巧就是因为我没注意到一次只能走一步的条件,所以想到了这样的用例:
k = 7, row = 15, col = 13
,当col = 0时,row允许的值是0-7
,10-14
。注意到了吗,中间是会断开的!10-14
区间段也被允许是因为它们位数和加起来后相当于1-5
!这样的话,其实可以在算到1-5
时就每格多算一格,因为10-14
这里也会重复。所以我就想到了将index当成系数表示该行可以算作几格,这样就不用把所有的行都算一遍了。
事实上,col也可以进行相同的处理,我去更改下代码好了。
Code 改进版
# -*- coding:utf-8 -*-
class Solution:
def movingCount(self, threshold, rows, cols):
# write code here
if threshold == 0:
return 0
row = self.calIndex(rows, threshold)
col = self.calIndex(cols, threshold)
res = 0
for i in range(len(col)):
minus = threshold - i
if minus >= 0:
for j in row[:minus + 1]:
res += j * col[i]
return res
def calIndex(self, line, threshold):
index = [0] * line
for i in range(line):
cnt = self.cnt(i)
if cnt <= threshold:
index[cnt] += 1
else:#去掉就是算除去一次一步条件下机器人可达的格子数
break#去掉就是算除去一次一步条件下机器人可达的格子数
return index
def cnt(self, num):
res = num % 10
num /= 10
while num:
res += num % 10
num /= 10
return res
这下就更加精简了,总的思想就是行列都算出来每一格等同于多少格,然后相乘即可,好好体会下吧,自己画个图应该就明白了。