l 问题描述
给定N*N字母矩阵,从任意点出发,上,下,左,右移动,在规定方向连续匹配给定的单词序列。即称为命中,否则不命中,
字符矩阵中的字母仅能使用一次,不能在同一单元格停留两次。字符矩阵最大50*50,都为大写字母。
输入1为字母矩阵,输入2为字母序列,输出是否匹配。
要求实现函数
int FindStat(const char *Map, unsigned int iArrN, const char *PathStr)
【输入】
Map: 给定的字母矩阵
iArrN: 字母矩阵的行数
PathStr: 给定的字母序列
【输出】无
【返回】是否能找到命中的单词序列,命中返回1,否则返回0
注:输入矩阵是以一维形式保存的二维数组,
比如输入为{‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘F’,’G’, ‘H’, ‘I’},
实际上表示如下3*3的矩阵
‘A’,’B’,’C’,
‘D’,’E’,’F’,
‘G’,’H’,’I’
2. 示例
输入:"ABCFEDGHI", 3, "ABCDEFGHI"
返回:1
输入:"ABCFEDGAI", 3, "ABCDEA"
返回: 0
输入: "AAAA", 2, "AAAA"
给定N*N字母矩阵,从任意点出发,上,下,左,右移动,在规定方向连续匹配给定的单词序列。即称为命中,否则不命中,
字符矩阵中的字母仅能使用一次,不能在同一单元格停留两次。字符矩阵最大50*50,都为大写字母。
输入1为字母矩阵,输入2为字母序列,输出是否匹配。
要求实现函数
int FindStat(const char *Map, unsigned int iArrN, const char *PathStr)
【输入】
Map: 给定的字母矩阵
iArrN: 字母矩阵的行数
PathStr: 给定的字母序列
【输出】无
【返回】是否能找到命中的单词序列,命中返回1,否则返回0
注:输入矩阵是以一维形式保存的二维数组,
比如输入为{‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘F’,’G’, ‘H’, ‘I’},
实际上表示如下3*3的矩阵
‘A’,’B’,’C’,
‘D’,’E’,’F’,
‘G’,’H’,’I’
2. 示例
输入:"ABCFEDGHI", 3, "ABCDEFGHI"
返回:1
输入:"ABCFEDGAI", 3, "ABCDEA"
返回:1
返回: 0
输入: "AAAA", 2, "AAAA"
返回:1
预备知识:
在C语言中 strchr 和 strstr函数都被包含在<string.h>头文件中,
也就是要调用它们时要在程序前面包含<string.h>头文件,也就是写这个语句:
strchr函数原型:char * strchr(char * str, int ch);
功能就是找出在字符串str中第一次出项字符ch的位置,找到就返回该字符位置的指针(
也就是返回该字符在字符串中的地址的位置),找不到就返回空指针(就是 null)。
strstr 函数原型: char * strstr(char * str1,char * str2);
功能就是找出在字符串str1中第一次出项字符串str2的位置(也就是说字符串sr1中要包含有字符串str2),
找到就返回该字符串位置的指针(也就是返回字符串str2在字符串str1中的地址的位置),找不到就返回空指针(就是 null)。
它们一个是求一个字符在字符串中得位置,另一个是求一个字符串在另一个字符串中的位置。
思路:路径查找问题依然是一个回溯法,注意两点:
1. 尝试过的位置如果不合适,要回溯回来。
2. 如果一个字符串检测完毕,需要将visited复位,以作下一次的尝试。
#include<iostream>
using namespace std;
int visited[50][50]={0};
int dfs(const char *Map, unsigned int iArrN, const char *PathStr, int row, int column){
if (*PathStr=='\0'){//结束条件
return 1;
}
//以(row,column)为起点,上、下、左、右 查找。
//向上
if(row>0 && !visited[row-1][column] && Map[(row-1)*iArrN + column]==*PathStr){
visited[row-1][column]=1;//回溯
if(
dfs(Map, iArrN, PathStr+1, row-1, column)==1
)
return 1;
else
visited[row-1][column]=0;//回溯
}
//向下
if( row<iArrN-1 && !visited[row+1][column] && Map[(row+1)*iArrN + column]==*PathStr ){
visited[row+1][column]=1;
if(
dfs(Map, iArrN, PathStr+1, row+1, column)==1
)
return 1;
else
visited[row+1][column]=0;//
}
//向左
if( column>0 && !visited[row][column-1] && Map[row*iArrN + column-1]==*PathStr ){
visited[row][column-1]=1;
if(
dfs(Map, iArrN, PathStr+1, row, column-1)==1
)
return 1;
else
visited[row][column-1]=0;
}
//向右
if(column<iArrN-1 && !visited[row][column+1] && Map[row*iArrN + column+1]==*PathStr ){
visited[row][column+1]=1;
if(
dfs(Map, iArrN, PathStr+1, row, column+1)==1
)
return 1;
else
visited[row][column+1]=0;
}
return 0;
}
int FindStat(const char *Map, unsigned int iArrN, const char *PathStr){
const char *pos=Map;
int location,row,column;
while( (pos=strchr(pos,*PathStr)) != NULL ){//寻找入口
location=pos-Map;
row=location / iArrN;//将要尝试的列
column=location % iArrN;//将要尝试的行
visited[row][column]=1;
if (1==dfs(Map,iArrN,PathStr+1,row,column)){
//记得visited是一个公共的数组,上一个用过之后需要将其复位------出bug
for(int i=0;i<50;++i)
for(int j=0;j<50;++j)
visited[i][j]=0;
return 1;
}
visited[row][column]=0;
++pos;
}
//记得visited是一个公共的数组,上一个用过之后需要将其复位------出bug
for(int i=0;i<50;++i)
for(int j=0;j<50;++j)
visited[i][j]=0;
//执行到这里说明不存在,需要返回0
return 0;
}
int main()
{
char *Map[3]={"ABCFEDGAI","ABCFEDGHI","ABABABABABABABABABABABABA"};
char *PathStr[3]={"ABCDEA","ABCDEFGHI","ABABABBA"};
int iArrN[3]={3,3,5};
for(int i=0;i<3;++i){
printf("%d\n",FindStat(Map[i],iArrN[i],PathStr[i]));
}
return 0;
}