计蒜客题解——T1244:单词序列

题目相关

题目链接

计蒜客 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;	 
}
发布了208 篇原创文章 · 获赞 128 · 访问量 105万+

猜你喜欢

转载自blog.csdn.net/justidle/article/details/104682089