题目相关
题目链接
计蒜客 OJ,https://nanti.jisuanke.com/t/T1244。
我的 OJ,http://47.110.135.197/problem.php?id=4766。
题目描述
蒜头君给出两个单词(开始单词和结束单词)以及一个词典。找出从开始单词转换到结束单词,所需要的最短转换序列。转换的规则如下:
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
题目分析
题意分析
从开始单词转换到结束单词,每次只能改变一个字母,转换过程中出现的单词(除开始单词和结束单词)必须存在于词典中。求输出转换序列的长度。
样例数据分析
样例输入 hit,词典为 [hot,dot,dog,lot,log,mot]。按照规定每次只能改变一个字母,转换的单词必须在词典表中。因此我们可以画出下图的变换过程:
从上图可以看出,hit 变化到 log 有两种路径:
1、hit -> hot -> dot -> dog -> cog,本方法序列长度为 5。
2、hit -> hot -> lot -> log -> cog,本方法序列长度为 5。
所以最终输出的结果为 5。
技术细节
如何判断从 hit 变成 hot 是变化了一个字母?
由于本题单词长度不超过 5,因此可以使用暴力比较方法对两个字符串进行比较。相关代码如下:
//比较字符串a和b是否差一个字符
bool judge(const string &a, const string &b) {
int len = max(a.length(), b.length());
int ans = 0;
for (int i=0; i<len; i++) {
if (a[i]!=b[i]) {
ans++;
if (ans>1) {
return false;
}
}
}
return 1==ans?true:false;
}
如何判断某个字符串已经访问过?
通过设置标志为来实现。
数据结构定义
个人还是趋向定义一个结构体,将所有数据包括在里面。
typedef struct _NODE {
string data;//字符串
int dis;//距离
bool vis;//访问性
} NODE;
编程思路
从上面的样例数据分析,本题是一道 BFS 模板题。大致可以分以下几个步骤:
1、读入数据。
2、将开始数据加入到队列中。
3、使用 BFS 遍历。
AC 参考代码
#include <bits/stdc++.h>
using namespace std;
typedef struct _NODE {
string data;//字符串
int dis;//距离
bool vis;//访问性
} NODE;
const int MAXN = 30+4;
NODE a[MAXN];
//判断两个字符串是否差一个字符
bool judge(const string &a, const string &b) {
int len = max(a.length(), b.length());
int ans = 0;
for (int i=0; i<len; i++) {
if (a[i]!=b[i]) {
ans++;
if (ans>1) {
return false;
}
}
}
return (1==ans)?true:false;
}
int main() {
NODE st = {};//开始单词
NODE ed = {};//结束单词
cin >> st.data >> ed.data;
int cnt = 0;
while (cin>>a[cnt++].data);
queue<NODE> q;//队列
st.vis = true;
st.dis = 1;
q.push(st);
while (false == q.empty()) {
//取出队首元素
NODE cur = q.front();
q.pop();
//判断能否变成结束单词
if (true==judge(cur.data, ed.data)) {
cout << cur.dis+1 << endl;
return 0;
}
//检查词典表那个单词可以插入
for (int i=0; i<cnt; i++) {
if (false==a[i].vis && true==judge(cur.data, a[i].data)) {
a[i].vis = true;
a[i].dis = cur.dis+1;
q.push(a[i]);
}
}
}
printf("0\n");
return 0;
}