此题依旧采用暴力法&BFS两种方法。
首先要看懂题目,例如如 let m = 20, n = 15, k = 9,下图绿色的代表能走的,红色的代表超过个位数的sum。图源于此。
但题目是有限制的,“每次可以向左、右、上、下移动一格(不能移动到方格外)”,意思是右下角那一块绿色没办法走到(机器人不可能穿墙)。
我们首先使用暴力求解,思路:从左到右,从上到下遍历,判断当前位置的左边和上边机器人是否可以走到,如果走得到,则说明当前的位置也可以走得到。
int movingCount(int m, int n, int k) {
int m_num=0,n_num=0;
int res = 1;
int flag[m][n];
memset(flag,0,sizeof(flag));
flag[0][0] = 1;
for(int i = 0; i < m; i ++)
{
m_num = i/10+i%10;
if(m_num > k) {
continue;
}
for(int j = 0; j < n; j++)
{
n_num = j/10+j%10;
if( ((j>0 && flag[i][j-1] == 1) ||
(i> 0 && flag[i-1][j] == 1) )
&& (m_num+n_num <=k))
{
res++;
flag[i][j] = 1;
}
}
}
return res;
除了使用暴力法,我们还可以使用BFS,也就是广度优先遍历,之前写腐烂的橘子写过,但又忘了,这种题型刷的太少,又来发现原来是有模板的!广度优先遍历的原理咱就不说了,上一个注释版本的demo。
上面暴力法是通过判断当前位置的左边和上面是否能走,从而来判断当前位置是否能走,而BFS则是向下搜索,所以只需要搜索当前位置的下面和右边的位置是否能走到。刚好相反。
//得到当前位置个数之和
int indexsum(int num_i, int num_j)
{
int sum = 0;
while(num_i !=0)
{
sum+= num_i%10 ;
num_i /= 10;
}
while(num_j !=0)
{
sum+= num_j%10 ;
num_j/= 10;
}
return sum;
}
int movingCount(int m, int n, int k) {
//广度优先遍历
//定义下面和右边两个方向
int direction[2][2]={{0, 1}, {1, 0}};
vector<vector<int>> visited(m,vector<int>(n,0)); //存放当前值是否能走,能走置1
queue<pair<int,int>> q; //队列,存放坐标
q.push({0,0}); //原点入队
int res = 0; //存放结果
visited[0][0] = 1; //原点是一定可以走的
//BFS算法
while(!q.empty())
{
auto front = q.front(); //先获得队列的值
q.pop(); //把这个值去掉
int x = front.first; //得到当前位置
int y = front.second;
res+=1; //能走的数+1
//遍历两个方向
for(int i = 0 ; i < 2; i ++)
{
int new_x = x + direction[i][0]; //得到新坐标
int new_y = y + direction[i][1];
//如果新坐标超出范围或不满足要求,则continue,意思是这个分支没有下一个结点了。
if(new_x < 0 || new_x >= m || new_y < 0 || new_y >=n || visited[new_x][new_y] == 1 || indexsum(new_x,new_y) > k )
{
continue;
}
//如果满足要求,则说明可以搜索到,那么入队。
q.push({new_x, new_y});
//同时把这个点标记为能走。
visited[new_x][new_y] = 1 ;
}
}
//全部节点走完
return res;
}
那么,这个模板是什么呢?
当不需要确定当前遍历到哪一层:
while queue 不空:
cur = queue.pop()
for 节点 in cur的所有相邻节点:
if 该节点有效且未访问过:
queue.push(该节点)
作者:fuxuemingzhu
链接:https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof/solution/bfsmo-ban-yi-ci-bei-hui-chu-chu-shi-yong-by-fuxuem/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
当需要确定当前遍历到哪一层:
level = 0
while queue 不空:
size = queue.size()
while (size --) {
cur = queue.pop()
for 节点 in cur的所有相邻节点:
if 该节点有效且未被访问过:
queue.push(该节点)
}
level ++;
作者:fuxuemingzhu
链接:https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof/solution/bfsmo-ban-yi-ci-bei-hui-chu-chu-shi-yong-by-fuxuem/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
上面的BFS就是通过第一个模板写的,并且对原作者所写进行了优化。
https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof/solution/da-lao-jiu-shi-da-lao-zi-ji-xiang-po-nao-dai-du-xi/
https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof/solution/bfsmo-ban-yi-ci-bei-hui-chu-chu-shi-yong-by-fuxuem/