回溯——矩阵中路径问题(0,1矩阵中最优路径、矩阵中的路径、机器人的运动范围)
2017-03-11 22:13
656 查看
问题一: 给定一个rows*cols 大小的0,1矩阵,给出起点和终点坐标,0可以走,1不可以走,每次只能向上下左右,走一步,求出从起点到终点的最短路径;
解题思路:回溯法解决的经典问题,由于回溯的递归特性,首先要找到递归结束的条件,本题终点就是结束条件(在递归结束判断此路径是否为最优路径)
其次,找出递归的条件,本题是坐标x,y的值在合理范围内,并且此点没有走过
回溯的位置与条件,当第n个位置四周都为1,都不可以走,则需要回到第n-1位置,只需将第n的位置弹出,设置为没有走过。
//*matrix表示二维0,1矩阵; rows表示矩阵的行数,cols表示矩阵的列数,
//*p1表示起点坐标,p2表示终点坐标,bool *visited用来标记矩阵中的点是否走过没有为0,走过为1;
//*vector<Point>& totalPath 用来盛放最新求出的路径,vector<Point>& bestPath用来盛放最短的路径,这两个参数都加了引用,表示指向实参的位置,而不是重新开辟新的变量,因为在递归调用时,这两个参数会随之改变。
<
4000
p>问题二:矩阵中的路径
请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。 例如[a b c e s f c s
a d e e]是3*4矩阵,其包含字符串"bcced"的路径,但是矩阵中不包含“abcb”路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。
解题思路和上题相同,主要是终止条件,递归条件不同,要求的返回值情况不同,所以要注意递归的情况的使用
问题三:机器人的运动范围
地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。
例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?
解题思路:此题考查思路和上题相同,也考查了整数的每个位数值的和,但是终止条件不是很明确,但是递归的条件很明确,所以只要递归结束就可以返回值,为什么这里不用写回溯的情况呢,还不是很明白,之后看了一篇博客,http://blog.csdn.net/jinzhao1993/article/details/72850641
知道什么时候要回溯,什么时候不要了 和设置的判断变量是不是全局变量。count是全局变量,flag不是全局变量
这和四叉树的深度很相似,就是四叉树的深度遍历,我当时没有没有联想到~~~~
如果先让你做多叉树的广度深度遍历,然后再让你做这个题,可以就好想一点了。。
解题思路:回溯法解决的经典问题,由于回溯的递归特性,首先要找到递归结束的条件,本题终点就是结束条件(在递归结束判断此路径是否为最优路径)
其次,找出递归的条件,本题是坐标x,y的值在合理范围内,并且此点没有走过
回溯的位置与条件,当第n个位置四周都为1,都不可以走,则需要回到第n-1位置,只需将第n的位置弹出,设置为没有走过。
//*matrix表示二维0,1矩阵; rows表示矩阵的行数,cols表示矩阵的列数,
//*p1表示起点坐标,p2表示终点坐标,bool *visited用来标记矩阵中的点是否走过没有为0,走过为1;
//*vector<Point>& totalPath 用来盛放最新求出的路径,vector<Point>& bestPath用来盛放最短的路径,这两个参数都加了引用,表示指向实参的位置,而不是重新开辟新的变量,因为在递归调用时,这两个参数会随之改变。
void findBestPath(int *matrix,int rows,int cols,Point p1,Point p2,bool *visited,vector<Point>& totalPath,vector<Point>& bestPath) { int x = p1.x, y = p1.y; if(visited[x*cols + y] == false && matrix[x*cols + y] == 0) { totalPath.push_back(p1); visited[x*cols + y] = true; if(x == p2.x && y == p2.y)//这个结束判断语句什么时候写 { //如果是找到的第一条路径,直接添加到bestpath中 int i = 0; if(bestPath.size() == 0) { while(i < totalPath.size()) { bestPath.push_back(totalPath[i]); i++; } } else { //选择一个最短的路径放到bestPath中 if(bestPath.size() > totalPath.size()) { bestPath.clear(); i = 0; while(i < totalPath.size()) { bestPath.push_back(totalPath[i]); i++; } } } } if((x-1)>= 0){findBestPath(matrix,rows,cols,Point((x-1),y),p2,visited,totalPath,bestPath);} if((x+1)<rows){findBestPath(matrix,rows,cols,Point((x+1),y),p2,visited,totalPath,bestPath);} if((y-1)>= 0){findBestPath(matrix,rows,cols,Point(x,(y-1)),p2,visited,totalPath,bestPath);} if((y+1)<cols){findBestPath(matrix,rows,cols,Point(x,(y+1)),p2,visited,totalPath,bestPath);} //回溯很重要,理解这个问题,要不要加判断,什么时候写,什么时候不写这个回溯,终点为终止条件 // if(x != p2.x || y != p2.y){ totalPath.pop_back(); visited[x*cols + y] = false; // } } return; }
<
4000
p>问题二:矩阵中的路径
请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。 例如[a b c e s f c s
a d e e]是3*4矩阵,其包含字符串"bcced"的路径,但是矩阵中不包含“abcb”路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。
解题思路和上题相同,主要是终止条件,递归条件不同,要求的返回值情况不同,所以要注意递归的情况的使用
bool flag = false; bool hasPath(char* matrix, int rows, int cols, char* str) { if(matrix == NULL || rows < 1 || cols < 1 || str == NULL) { return false; } bool *visited = new bool[rows * cols]; memset(visited, 1 ,rows * cols);//默认值为true都可以走 int count = 0;//记录走的点的个数 //找出开始走的点位置 for(int i = 0; i < rows;i++){ for(int j = 0;j < cols;j++){ if(matrix[i*cols + j]== str[count]) { flag = hasNextNode(matrix,rows,cols,i,j,str,count,visited); } } } delete[] visited; return flag; } //找出下一个节点 bool hasNextNode(char* matrix, int rows, int cols,int x,int y, char* str,int count,bool * visited) { if(str[count] == '\0')//判断str是否已经走完 { return true; } if(x >= 0 && x < rows && y >=0 && y < cols && matrix[x*cols + y] == str[count] && visited[x*cols + y]) { //matrix[x*cols + y] = '0';//char*的类型值不能修改,所以这么来判断是否走过是不对的。 visited[x*cols + y] = false;//走过不能走了,为false count++;//将str的位置后移 //找出下一个点上下左右 flag = hasNextNode(matrix,rows,cols,(x-1),y,str,count,visited) || hasNextNode(matrix,rows,cols,(x+1),y,str,count,visited) || hasNextNode(matrix,rows,cols,x,(y-1),str,count,visited) || hasNextNode(matrix,rows,cols,x,(y+1),str,count,visited); if(flag == false)//flag不是全局变量 { --count; visited[x*cols + y] = true;//回溯,表示此点还可以走 } } return flag; }
问题三:机器人的运动范围
地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。
例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?
解题思路:此题考查思路和上题相同,也考查了整数的每个位数值的和,但是终止条件不是很明确,但是递归的条件很明确,所以只要递归结束就可以返回值,为什么这里不用写回溯的情况呢,还不是很明白,之后看了一篇博客,http://blog.csdn.net/jinzhao1993/article/details/72850641
知道什么时候要回溯,什么时候不要了 和设置的判断变量是不是全局变量。count是全局变量,flag不是全局变量
int movingCount(int threshold, int rows, int cols) { if(rows<0 || cols<0 )return 0; bool *visited = new bool[rows * cols];//定义判断此点是否走过的数组并赋值为true memset(visited,1,rows * cols); int count = movingNextPoint(threshold,rows,cols,0,0,visited); delete []visited; return count; } int movingNextPoint(int threshold, int rows, int cols,int x,int y,bool *visited) { int count = 0; if(x >=0 && x < rows && y >= 0 && y < cols && (sumPerInt(x) + sumPerInt(y))<= threshold && visited[x*cols + y] == true) { visited[x*cols + y] = false;//表示此点已经走过不可以再走了 count = 1 + movingNextPoint(threshold,rows,cols,(x-1),y,visited) + movingNextPoint(threshold,rows,cols,(x+1),y,visited) + movingNextPoint(threshold,rows,cols,x,(y-1),visited) + movingNextPoint(threshold,rows,cols,x,(y+1),visited); } return count; } //求整数各个位数之和 int sumPerInt(int num){ int sum = 0; while(num > 0){ sum += num % 10; num /= 10; } return sum; }
这和四叉树的深度很相似,就是四叉树的深度遍历,我当时没有没有联想到~~~~
如果先让你做多叉树的广度深度遍历,然后再让你做这个题,可以就好想一点了。。
相关文章推荐
- 回溯——矩阵中路径问题(0,1矩阵中最优路径、矩阵中的路径、机器人的运动范围)
- 回溯——矩阵中路径问题(0,1矩阵中最优路径、矩阵中的路径、机器人的运动范围)
- 回溯——矩阵中路径问题(0,1矩阵中最优路径、矩阵中的路径、机器人的运动范围)
- 回溯——矩阵中路径问题(0,1矩阵中最优路径、矩阵中的路径、机器人的运动范围)
- 回溯——矩阵中路径问题(0,1矩阵中最优路径、矩阵中的路径、机器人的运动范围)
- 回溯——矩阵中路径问题(0,1矩阵中最优路径、矩阵中的路径、机器人的运动范围)
- OJ日常 | 回溯——矩阵中的路径、机器人的运动范围
- 【剑指offer】第十二题(矩阵中的路径)和 第十三题(机器人的运动范围)
- 剑指offer 机器人的运动范围 矩阵中的路径 滑动窗口最大值 次数超过一半的数 连续子数组的最大和
- 矩阵中的路径(dfs深搜), 机器人的运动范围(dfs深搜)
- JAVA回溯, 实现 矩阵中的路径寻找问题
- 剑指offer——机器人的运动范围(回溯)
- 剑指第13题:机器人的运动范围------回溯法
- 矩阵行走路径问题
- 迷宫问题一 找到迷宫的一条路径(DFS+回溯)
- 最优路径问题 mod 4 的最小值
- Arcgis for JS实现台风运动路径与影像范围的显示
- 迷宫问题二 统计路径条数(dfs+回溯)
- 【网络流与线性规划24题】【机器人路径规划问题】【IDA*】【题解】
- Java利用回溯思想解决迷宫问题(寻找最短路径)