初看这题,以为这题是逃迷宫那种题,但是后来发现还是有点差别的。这里贴出走迷宫这道题链接:Lost in maze
继续来说这道题,本题判断在一个字符矩阵中,是否可以找出由相邻的元素组成的target字符串。
For example,
Given board =
[ ['A','B','C','E'], ['S','F','C','S'], ['A','D','E','E'] ]
word
=
"ABCCED"
, -> returns
true
,
word
=
"SEE"
, -> returns
true
,
word = "ABCB"
, -> returns false
.
对比一下那个走迷宫的题,那道题是起点固定,只能从起点出发开始深搜。然而这道题却是起点是矩阵中的任何一个点,所以我们在Main函数中就用一个双重循环,循环起点,然后从每个起点开始深搜。
有点小蓝瘦,做了几道回溯的题了,dfs还是不会写,写了一下午。我用k表示匹配到target字符串的位置,另外visited[][]辅助数组用来标记这个位置是否被检查过。
if(k==word.length())//说明找到一种解。返回1
接下来检查是否出界、被检查过、是否和当前位置的字符匹配。不满足其一都直接return false;(把检查放在第一步是为了防止后面数组越界)
如果满足上述条件,就循环上下左右四个位置,每个位置都进行递归,只要一个位置结果为1,跳出循环返回1;
最后千万别忘了,回溯的过程,将visited清零。是放在for的外面的!
上面的这三个过程的顺序不能变,就这个顺序搞了一下午,得到的一个结论是,dfs判断的是当前的的状态!
下一个位置的放到下一个递归去判断。
另外说一个小细节,我在dfs的参数里把辅助数组visted 数组加了进去,这是错误的,原因是C语言中,二维数组作为形参第二维的维数必须说明
int a[][]
int a[3][]//例如这两个都是错的
而实参可以直接用数组名
详见AC代码:
class Solution {
public:
int X[4]={0,0,1,-1};int Y[4]={1,-1,0,0};
bool visited[1000][1000];
bool exist(vector<vector<char>>& board, string word) {
int l=board[0].size();int w=board.size();
memset(visited,0,sizeof(bool));
for(int i=0;i<w;i++){
for(int j=0;j<l;j++){
if(dfs(board,word,i,j,0))
return 1;
}
}
return 0;
}
bool dfs(vector<vector<char>> &board,string word,int x,int y,int k)
{
bool ans;
if(k==word.length()){return 1;}
if(x<0||x>=board.size()||y<0||y>=board[0].size()||visited[x][y]||board[x][y]!=word[k]){
return 0;
}
else{
visited[x][y]=1;
for(int i=0;i<4;i++) {
ans= dfs(board,word,x+X[i],y+Y[i],k+1);
if(ans)break;
}
}
visited[x][y]=0;
return ans;
}
};