【LeetCode】【回溯法】剑指 Offer 13. 机器人的运动范围 思路解析和代码(dfs:何时需要标记,何时需要撤销)

剑指 Offer 13. 机器人的运动范围

题目链接

个人思路

思路

已经是二刷了,思路很清楚,也知道采用dfs,也知道如何进行深度优先搜索,但是对于dfs中何时需要标记数据,何时需要撤销操作还是有点雾水

对于此题来说,目标是要统计机器人能覆盖的格子数,而每次递归,递归体的for循环都是从0开始的,为了保证不重复访问那些已经访问过的格子,因此在dfs过程中不需要撤销操作,即不用对vis[tx][ty]进行撤销标记

对于求路径总条数、最短路径,dfs过程中都会探索出多条行走方式。因此存在这样的特殊场景:同一个点(并非终点,包括中间的点),可以有不同路径达到,只有进行撤销操作后,才能探索出多条完整的路径

for(int i = 0; i < 4; ++i){
	int tx = x + dir[i][0];
	int ty = y + dir[i][1];
	if(tx >= 0 && tx < m && ty >= 0 && ty < n && (getNum(tx) + getNum(ty) <= k) && vis[tx][ty] == false){
	    cnt++;
	    dfs(m, n, k, tx, ty, cnt);
	}
}

何时需要标记,何时需要撤销

  • 有的(部分)路径需要你访问多次,这时候回溯需要取消标记,不然无法访问了;有的路径只访问一次,就不需要取消标记。

1.如果是visit[i]这种标记,回溯后i点应该视为没访问过,所以需要还原,不管是全局变量还是局部。
2.vector用来记录过程路径的,回溯后最后push的那个值就没有用的价值,所以要pop还原,不管是全局变量还是局部。
3.history[i]这种,用来记录第i点的值(颜色或者数字…),一般回溯到i之前的点时,第i点的取值就无所谓了,对dfs递归不影响,所以不用还原,还原也不会错。
4.int ans这种记录全局的变量,全局变量需要还原,局部不需要。
————————————————
版权声明:本文为CSDN博主「TodorovChen」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/todorovchen/article/details/38534407

个人思路代码

class Solution {
public:
    int dir[4][2] = {{1, 0}, {-1, 0}, {0, -1}, {0, 1}};
    bool vis[105][105];
    int count = 1;
    int getNum(int num){
        int res = 0;
        int temp;
        while(num > 0){
            temp = num % 10;
            res += temp;
            num /= 10;
        }
        return res;
    }
    int movingCount(int m, int n, int k) {
        if(k == 0){
            return count;
        }
        dfs(m, n, k, 0, 0, count);
        return count;
    }

    void dfs(int m, int n, int k, int x, int y, int& cnt){


        // cout << x << " " << y << " " << cnt << endl;
        vis[x][y] = true;

        for(int i = 0; i < 4; ++i){
            int tx = x + dir[i][0];
            int ty = y + dir[i][1];
            if(tx >= 0 && tx < m && ty >= 0 && ty < n && (getNum(tx) + getNum(ty) <= k) && vis[tx][ty] == false){
                cnt++;
                dfs(m, n, k, tx, ty, cnt);
            }
        }
    }
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值