/**
首先在某个节点处,要调用递归来决定某个位置的下一步去哪,此时有4个选择,每个选择都会进入下一个递归
调用。当进入某个位置时,应当标记这个位置已访问过,避免之后又来到这里,从而重复计算,因此设计一个
boolean的数组,这里设计的二维,也可以通过压缩,使用一维数组来表征某个位置是否访问。二维就是记录
横纵坐标即第i行第j列的数据被访问了,直观,推荐新手用二维。接着就是边界条件和递归结束的条件的判断了。
*/
public class Solution {
public int movingCount(int threshold, int rows, int cols)
{
int[][] flag=new int[rows][cols];
help(0,0,threshold,rows,cols,flag);
return count;
}
public boolean isValid(int r, int c, int threshold)
{
int sum=0;
while(r>0)
{
sum+=r%10;
r=r/10;
}
while(c>0)
{
sum+=c%10;
c=c/10;
}
if(sum>threshold)
return false;
else
return true;
}
//统计能够走到的次数
public int count=0;
public void help(int i, int j, int threshold, int rows, int cols, int [][]flag)
{
if(i<0||i>=rows || j<0||j>=cols) return;
if(flag[i][j]==1) return;
if(!isValid(i,j,threshold)){
flag[i][j]=1;
return;
}
//无论是广度优先遍历还是深度优先遍历,我们一定要知道的时候遍历一定会有终止条件也就是要能够停止,
//不然程序就会陷入死循环,这个一定是我们做此类题目必须要注意的地方
flag[i][j]=1;
count++;
help(i-1,j,threshold,rows,cols,flag);
help(i+1,j,threshold,rows,cols,flag);
help(i,j-1,threshold,rows,cols,flag);
help(i,j+1,threshold,rows,cols,flag);
}
}
public class Solution {
public boolean hasPath(char[] matrix, int rows, int cols, char[] str)
{
for(int i=0;i<rows;i++)
{
for(int j=0;j<cols;j++)
{
//对矩阵中的每一个点都当作起始点,能交给程序去做的复杂遍历判断,都交给程序去完成
int flag[][]=new int[rows][cols];
if(subHasPath(matrix,rows,cols,str,i,j,0,flag))
return true;
}
}
return false;
}
public boolean subHasPath(char[] matrix, int rows, int cols, char[] str,int i,int j,int count, int [][]flag)
{
//使用DFS递归的回溯剪枝思想,即添加一些判断条件使得程序不再递归下去(递归终止条件)
if(matrix[i*cols+j]!=str[count] || flag[i][j]==1) return false;
//递归成功条件
if(count==str.length-1) return true;
//先假设i,j是正确的
flag[i][j]=1;
//递归的同时判断 下标
if(i<rows-1 && subHasPath(matrix,rows,cols,str,i+1,j,count+1,flag)) return true;
if(i>0 && subHasPath(matrix,rows,cols,str,i-1,j,count+1,flag)) return true;
if(j<cols-1 && subHasPath(matrix,rows,cols,str,i,j+1,count+1,flag)) return true;
if(j>0 && subHasPath(matrix,rows,cols,str,i,j-1,count+1,flag)) return true;
// i,j不是解,再置为0
flag[i][j]=0;
return false;
}
}