字串变换(AcWing, NOIP2002提高组)

题目描述:

字串变换(AcWing, NOIP2002提高组)_第1张图片

题目链接: 

https://www.acwing.com/problem/content/192/

思路:

这个题是要求“最小步数”,比较容易想到是用BFS来进行搜索,但是直接BFS的话状态数太多了,时间复杂度会到:O((LN)^{10}),其中L是字符串的长度,N是一个字符串的可能变换到的后继字符串数。肯定会超时。

因此,本题使用了“双向搜索”的技巧,i.e. 分别从起点和终点向中间进行搜索,如果搜到了“公共点”,那这个公共点就是答案。 使用双向搜索的时间复杂度是:O(2(LN)^{5})

在具体实现的时候,使用了一些实现技巧(需要注意!):

1. 优先从队列比较小的那个方向进行搜索

2. 当一个方向搜索完了,还没有搜到和另一个方向的公共点时,就直接结束,此时一定无解了! 这是因为: 不妨假设是正向搜索完了,还没有搜到与另一个方向的公共点。注意到我们的“双向搜索”本质上和“单向搜索”的答案(有解性)应当是相同的。而如果只用“单向搜索”搜不到答案,那么双向搜索也一定搜不到答案(反证法可证),而现在“正向搜索”搜完了,这实际上相当于“单向搜索”搜索完了,也没搜到答案,因此“双向搜索”就没有必要继续进行下去了,因为一定不会有答案了。

3. 使用了string 类的substr来完成取子串,string类的+ 来实现字符串拼接, string类的=来实现字符串相等的判断

4. 使用unordered_map,不用map, 这样会更快

代码:

#include
#include
#include
#include
#include
#include
using namespace std;
const int N=7;
queue qa,qb;
string a[N],b[N];
unordered_map ma,mb;
string A,B;
int n;

int extend(string cur,int flag){
	if(flag==0){
		for(int i=0;i> A>> B;
	n=1;
	while(cin >> a[n] >> b[n]) n++;
	n--;
	int res=bfs();
	if(res>10) printf("NO ANSWER!");
	else printf("%d",res);
	
	return 0;
}

你可能感兴趣的:(算法题,动态规划,算法,广度优先,bfs)