洛谷P1032字串变换题解--zhengjun

题目描述

已知有两个字串 A , B A,B 及一组字串变换的规则(至多 6 6 个规则):

A 1 A_1 - > B 1 B_1
A 2 A_2 - > B 2 B_2

规则的含义为:在 A A 中的子串 A 1 A_1 可以变换为 B 1 B_1 A 2 A_2 可以变换为 B 2 B_2 ···

例如:A=abcd,B=xyz

变换规则为:

abcxuudyyyz

则此时, A A 可以经过一系列的变换变为 B B ,其变换的过程为:

abcdxudxyxyz

共进行了 3 3 次变换,使得 A A 变换为 B B

输入格式

输入格式如下:

A A B B
A 1 A_1 B 1 B_1
A 2 A_2 B 2 B_2 |-> 变换规则

··· ··· /

所有字符串长度的上限为 20 20

输出格式

输出至屏幕。格式如下:

若在 10 10 步(包含 10 10 步)以内能将 A A 变换为 B B ,则输出最少的变换步数;否则输出NO ANSWER!

输入输出样例

输入 #1 复制
abcd xyz
abc xu
ud y
y yz
输出 #1 复制
3

思路

首先,既然告诉了我们数据这么小,那么一定就是一个搜索,那么,是 d f s dfs 好还是 b f s bfs 好呢,因为我们要求的是最小的变换次数,所以 d f s dfs 要把整张图搜完了才能得到最终答案,而 b f s bfs 就只要第一次搜到就是最小变换次数了,所以,当然要用 b f s bfs

代码

#include<bits/stdc++.h>
using namespace std;
string a[7],b[7];
int n;
map<string,int> f;//剪枝,如果这个字符串已经搜过了,就不用再搜了
struct zj{
	string s;//当前的字符串
	int k;//所用步数
};
int bfs(){
	queue<zj> q;
	q.push(zj{a[0],0});
	while(!q.empty()){
		zj x=q.front();
		q.pop();
		if(x.k==10)//没必要再搜了
		    continue;
		for(int i=1;i<=n;i++){
			for(int pos=x.s.find(a[i],0);pos!=-1;pos=x.s.find(a[i],pos+1)){
			//a.find(b,x)表示在a这个字符串中从第x个字符寻找b这个字符串,如果没找到,返回-1
				string t=x.s;
				t.replace(pos,a[i].length(),b[i]);
				//这个a.replace(x,len,b)表示在字符串a的第x个字符后的len个字符(包括第x个字符)替换成b这个字符串
				if(!f[t]){//前面的剪枝
					if(t==b[0])//找到了解
						return x.k+1;
					f[t]=1;//标记
					q.push(zj{t,x.k+1});
				}
			}
		}
	}
	return -1;//找不到
}
int main(){
	while(cin>>a[n]>>b[n])
	    n++;
	n--;//最后n比原来的n大1
	int ans=bfs();
	if(ans!=-1)
	    printf("%d",ans);
	else printf("NO ANSWER!");
	return 0;
}

谢谢–zhengjun

发布了48 篇原创文章 · 获赞 49 · 访问量 2135

猜你喜欢

转载自blog.csdn.net/A_zjzj/article/details/104836167
今日推荐