noi题库 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

题解:

bfs搜索

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<map>
using namespace std;
const int inf = 233333;
int tot = 0;
struct ss
{
	string sa;
	int dis;
}s[333];
string b;
queue <ss> q;
map<string, int> used;
int bfs(string a)
{
	q.push((ss){a, 1});
	used[a] = 1;
	while(!q.empty())
	{
		ss u = q.front();
		q.pop();
		int lenu = u.sa.length();
		if(u.sa == b)
			return u.dis;
		int ls = 0;
		for(int j = 0;j < lenu;j ++)
		{
			if(u.sa[j] != b[j])
				ls++;
		}
		if(ls == 1)
		{
			return u.dis+1;
		}
		for(int i = 1;i <= tot;i ++)
		{
			ls = 0;
			for(int j = 0;j < lenu;j ++)
			{
				if(s[i].sa[j] != u.sa[j])
					ls++;
			}
			if(ls == 1)
			{
				if(used[s[i].sa])
					continue;
				s[i].dis = min(u.dis + 1, s[i].dis);
				q.push(s[i]);
				used[s[i].sa] = 1;
				ls = 0;
				if(s[i].sa == b)
					return s[i].dis;
				for(int j = 0;j < lenu;j ++)
				{
					if(s[i].sa[j] != b[j])
						ls++;
				}
				if(ls == 1)
				{
					return s[i].dis+1;
				}
			}
		}
	}
	return 0;
}
int main()
{
	for(int i = 1;i <= 300;i ++)
	{
		s[i].dis = inf;
	}
	string a;
	cin>>a>>b;
	if(a.length() != b.length())
	{
		cout<<0;
		return 0;
	}
	int len = a.length();
	while(cin>>s[++tot].sa);
	cout<<bfs(a)<<endl;
	return 0;
}

 

上一篇
下一篇