洛谷 P1032 字串变换

写在前面

这题挺有意思的,让我无从下手······
看别人的题解都得看半天,看到有位大佬写了迭代深搜,我表示不会,还是老老实实的用bfs(广搜)来解决这道题吧

题目链接

点击这里

思路

题目要求最短步数,显然我们优先考虑bfs
我们可以开2个队列:
一个队列用于存放字符串,一个队列用于存放步数

由于字符串可能会出现重复,我们必须得剪枝,若当前字符串出现过,则将它标记为1,标记用哈希map最为合适
出现过的字符串直接将两个队列的队首出队,然后continue,进行下一次循环

我们枚举当前队列中队头那个串的每一个位置,对每一个位置枚举所有可能的转换手段,然后去尝试拼接
(这里推荐用string中replace函数,可以直接取代字符串中某一位置的子字符串
匹配成功,则将截取后的字符串放入队列,然后在将步数的队首+1,存入步数队列(一个字符串可能有多个匹配的子串,因此不能只匹配一次,需要匹配多次
最后判断步数队列的队首是否超过10即可

code

string a[8],b[8];
queue<string> q;
queue<int> step;
int k=1;
string x,y;
unordered_map<string,int> m;
int bfs(){
	string s,ss;
	while(!q.empty() && q.front()!=y && step.front()<=10){//队列不为空且可以进行操作
		if(m[q.front()]){//去重
			q.pop();
			step.pop();
			continue;
		}
		m[q.front()]=1;
		for(int i=1;i<=k;++i){
			s=q.front();
			while(1){//一个字符串需要多次匹配
				int t=s.find(a[i]);
				if(t==-1) break;
				ss=q.front();
				ss.replace(t,a[i].size(),b[i]);//替换字符串
				q.push(ss);
				step.push(step.front()+1);//步数+1
				s[t]=' ';//防止当前位置再次被匹配
			}
		}
		q.pop();
		step.pop();
	}
	if(q.empty()||step.front()>10) return -1;
	return step.front();
}
void solve(){
	cin >> x >> y;
	while(cin >>a[k] >>b[k]){
		k++;
	}
	k--;
	q.push(x);
	step.push(0);//首先存入0,防止队列为空
	int ans=bfs();
	if(ans==-1){
		cout << "NO ANSWER!";
	}
	else cout << ans;
	return ;
}
  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值