题目描述
链接:http://bailian.openjudge.cn/practice/4128/
总时间限制: 1000ms 内存限制: 1024kB
描述
给出两个单词(开始单词和结束单词)以及一个词典。找出从开始单词转换到结束单词,所需要的最短转换序列。转换的规则如下:
1、每次只能改变一个字母
2、转换过程中出现的单词(除开始单词和结束单词)必须存在于词典中
例如:
开始单词为:hit
结束单词为:cog
词典为:[hot,dot,dog,lot,log,mot]
那么一种可能的最短变换是: hit -> hot -> dot -> dog -> cog,
所以返回的结果是序列的长度5;
注意:
1、如果不能找到这种变换,则输出0;
2、词典中所有单词长度一样;
3、所有的单词都由小写字母构成;
4、开始单词和结束单词可以不在词典中。
输入
共两行,第一行为开始单词和结束单词(两个单词不同),以空格分开。第二行为若干的单词(各不相同),以空格分隔开来,表示词典。单词长度不超过5,单词个数不超过30。
输出
输出转换序列的长度。
样例输入
hit cog
hot dot dog lot log
样例输出
5
题解思路
题目的意思是,从字典中选择路径,使从给定起始结点能转移到给定终点结点的最短转移路径,从一个单词转移到另一个单词的转移条件是两个单词只能相差一个字母。
这是一个典型的bfs的问法,bfs比dfs的优点之一就是容易求最短路径,因为bfs总是从当前结点扩展到下一跳结点,入队之后,在当前结点的深度的所有结点已经被访问之后,访问深度加一的结点。因为要统计最短路径,就在构造队列结点的时候将step项加入,记录当前结点距离初始结点的距离。
解题代码
#include <cstdio>
#include <cstring>
#include <queue>
char dict[40][10];
int visited[40];
char s[10];
char e[10];
int test(char a[], char b[]){
int alen = strlen(a);
//int blen = strlen(b);
int cnt = 0;
for(int i = 0; i < alen; i++){
if(a[i] != b[i])
cnt ++;
}
return cnt;
}
struct state{
char * s;
int step;
state(){}
state(char * a, int b){s = a ; step = b;}
};
int main(){
scanf("%s%s", s, e);
int len;
for( len = 1; scanf("%s", dict[len]) != EOF; len++);
strcpy(dict[0], s);
strcpy(dict[len], e);
memset(visited, 0, sizeof(visited));
std::queue<state> q;
q.push(state(dict[0], 1));
visited[0] = 1;
while(!q.empty()){
state s = q.front();
if(strcmp(s.s, dict[len]) == 0){
printf("%d
", s.step);
break;
}
else{
for(int i = 0; i <= len ;i++){
if(!visited[i] && test(s.s, dict[i]) == 1){
visited[i] = 1;
q.push(state(dict[i],s.step + 1));
}
}
}
q.pop();
}
if(q.empty()){
printf("%d
", 0);
}
return 0;
}