剑指offer<算法>---------------回朔算法

矩阵中的路径

题目来源:牛客网

1、问题描述

请设计一个函数,用来判断在一个n乘m的矩阵中是否存在一条包含某长度为len的字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。 例如
矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。
数据范围:0 \le n,m \le 20\0≤n,m≤20 ,1\le len \le 25\1≤len≤25

2、思路解析

思路:DFS+回朔
题目说明是要在距震中找到连续字符串,所以在每次找到前边的字符,前边的字符就不能使用了,所以使用标记矩阵将使用过的位置标记,标记过的就不能再使用了,在主函数寻找第一个字符串的第一个字符,给次函数传入下一次检测的字符串的位置应该是1。因为每次检测到相同的字符时下标才会+1,所以在最会的判断是不是全找到时就不用判断找到的字符串和word字符串想等,直接判断索引是不是和字符串的长度相等,相等就直接返回true。还有如果这一次找到的字符是相等的但是下一次字符是不相等的就要回硕,因为在每次传参时都回传表达式所以,每次遇到不相等的字符是就会自动回硕,还有标志位在遇到不相等的字符是就会将当前位置置位1。

3、代码实现

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param matrix char字符型vector<vector<>> 
     * @param word string字符串 
     * @return bool布尔型
     */
    bool flag=false;
    int net[4][2]={{1,0},{-1,0},{0,-1},{0,1}};//上下左右
    //v***********标记矩阵
    void DFS(vector<vector<int>>&v,vector<vector<char>>&ch,
             int newx,int newy,int col,int row,string str,int&&index){
        //判断是不是符合条件
            
            if(index==str.size()){
                //符合条件
                
                flag=true;      return;
            }
        //设置使用过的位置为
       v[newx][newy]=1;
        for(int i=0;i<4;i++){
            //更新坐标
            int x=newx+net[i][0];
            int y=newy+net[i][1];
            //判断坐标是不是合法
            if(x<0||x>=row||y<0||y>=col) continue;
            //判断是不是符合条件
            if(v[x][y]==0&&str[index]==ch[x][y]){
                v[x][y]=1;
                //递归到下一层
                DFS(v,ch,x,y,col,row,str,index+1);
                //会说
                v[x][y]=0;
                
            }
        }
    }
    bool hasPath(vector<vector<char> >& matrix, string word) {
        // write code here
        if(matrix.empty()||word.empty()){
            return false;
        }
        int row=matrix.size();
        int col=matrix[0].size();
   
       
        for(int i=0;i<row;i++){
              vector<vector<int>> v(row,vector<int>(col,0));//标记矩阵
            for(int j=0;j<col;j++){
           
                //找到字符串的第一个字符
                if(matrix[i][j]==word[0]){
                    
                    //调用函数
                    //下一个字符从1开始
                    DFS(v,matrix,i,j,col,row,word,1);
                
                    if(flag){
                        return true;
                    }
                }
            }
        }
        return false;
        
        
    }
};

机器人的运动范围

题目来源:牛客网

1、问题描述

地上有一个 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 。请问该机器人能够达到多少个格子?

2、思路解析

思路:DFS+回朔
这一题和渲染算法很相似,同样也是从一点出发,每次都只能向四周移动,遇到不符合条件的就会停止移动从而转向另一个点继续移动这些点有一些特点就是上下左右都是;联系在一起的。这个题的不满点就是坐标之和不能大于特定的数字,所以在每次到一个点时都要判断是不是符合这个条件,要是不符合这个条件就会转向其他点。还有就是不能到达一定到达的点,所以还需要标记矩阵。在每个点周围找到符合条件的点就是转向这个点在这点个点周围再找符合条件点,如果周围的都不符合就会转到其他点。

3、代码实现

class Solution {
    int count=1;
public:
    int fun(int x){
        int sum=0;//和
        int num=0;//余数
        while(x){
            num=x%10;
            sum+=num;
            x/=10;
        }
        return sum;
    }
    int net[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
    
    void DFS(vector<vector<int>>&v,int row,int col,int newx,int newy,int num){
        v[newx][newy]=1;
        for(int i=0;i<4;i++){
            int x=newx+net[i][0];
            int y=newy+net[i][1];
            if(x<0||x>=row||y<0||y>=col){
                continue;
            }
            //标记矩阵
            //计算坐标
            int sum=fun(x)+fun(y);
            if(sum<=num&&v[x][y]==0){
                //递归
                //v[x][y]=1;
                count++;
                DFS(v,row,col,x,y,num);
            }
        }
    }
    int movingCount(int threshold, int rows, int cols) {
        vector<vector<int>> v(rows,vector<int>(cols ,0));
       
        
        DFS(v,rows,cols,0,0,threshold);
        return count;
    }
};
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

自首的小偷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值