题目来源:http://noi.openjudge.cn/ch0407/8468/
8468:单词序列
总时间限制: 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
-----------------------------------------------------
思路
解空间的无权最短路问题。类似nyoj21 三个水杯(搜索)。
不同点在于nyoj21 三个水杯(搜索)直接用三维数组存储了解空间,而本题用map存储字典,利用了map查询复杂度为O(logn)的特点。
-----------------------------------------------------
代码
// 解空间深搜求无权最短路
#include<iostream>
#include<fstream>
#include<map>
#include<string>
#include<queue>
using namespace std;
struct node {
string s;
int cnt;
node (string ss, int mycnt): s(ss), cnt(mycnt){}
};
map<string,bool> dic; // 单词在词典中且未访问过为1, 否则为0
int bfs(string Beg, string End)
{
if (Beg==End)
{
return 1;
}
string ss,ss1;
int slen,i,j;
char ch,ch1;
node nd(Beg, 1);
dic[Beg] = 0;
queue<node> qn;
qn.push(nd);
while (!qn.empty()) // 深搜模板
{
nd = qn.front();
ss = nd.s;
slen = ss.size();
qn.pop();
for (i=0; i<slen; i++)
{
ch = ss.at(i);
for (j=0; j<26; j++)
{
ch1 = 'a'+j;
if (ch1!=ch)
{
ss1 = ss;
ss1.at(i) = ch1;
if (ss1==End)
{
return nd.cnt+1;
}
if (dic[ss1])
{
node nd1(ss1,nd.cnt+1);
qn.push(nd1);
dic[ss1] = 0;
}
}
}
}
}
return 0;
}
int main()
{
#ifndef ONLINE_JUDGE
ifstream fin ("0407_8468.txt");
string Beg, End, tmp;
fin >> Beg >> End;
while (fin >> tmp)
{
dic[tmp] = 1;
}
fin.close();
cout << bfs(Beg,End);
return 0;
#endif
#ifdef ONLINE_JUDGE
string Beg, End, tmp;
cin >> Beg >> End;
while (cin >> tmp)
{
dic[tmp] = 1;
}
cout << bfs(Beg,End);
return 0;
#endif
}