华为编程大赛——路径查找
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; }