【做练习】单词序列(搜索)

题目

总时间限制: 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


分析

一看数据比较小,暴力搜索即可。dfs和bfs都可以。


代码实现

#include <set>
#include <string>
#include <iostream>
#include<stack>

#pragma warning(disable: 4996) //make Visual Studio happy

#define MAXLEN 5
#define MAXNUM 30
#define INF 0x7FFFFFFF

using std::set;
using std::string;
using std::cin;
using std::cout;

int wordLen;
set<char> possibleChars[MAXLEN];
string beg, end;
set<string> dictionary;

void Input()
{
	char buf[MAXLEN + 1];

	cin >> beg >> end;
	wordLen = beg.length();
	cin.get();

	string s;
	do {
		cin >> s;
		dictionary.insert(s);
		for (int i = 0; i < wordLen; i++)
			possibleChars[i].insert(s[i]);
	} while (cin.get() == ' ');

	for (int i = 0; i < wordLen; i++)
	{
		possibleChars[i].insert(beg[i]);
		possibleChars[i].insert(end[i]);
	}

}


// dfs
int MinDistToEnd(const string& s)
{
	if (s == end) return 0;
	
	int minDist = INF;

	for(int i = 0; i < wordLen; i++)
		for (char ch : possibleChars[i]) if (ch != s[i]) {
			string s_ = s;
			s_[i] = ch;
			if (s_ == end) 
				minDist = 1; // 更换后,即得到结束串
			else if (dictionary.find(s_) == dictionary.end())  // 更换后,不在字典内
				continue;
			else { //更换后在字典内
				dictionary.erase(s_);  // 字典中移除s_,避免它被再次搜索到
				int dist = MinDistToEnd(s_);
				dist = dist == INF ? INF : dist + 1;
				minDist = dist < minDist ? dist : minDist;
				dictionary.insert(s_); // 恢复s_在字典中
			}
		}
	

	return minDist;
}



int main()
{
	Input();
	int dist = MinDistToEnd(beg); 
	if (dist == INF) cout << 0;
	else cout << dist + 1;
	return 0;
	
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值