P1032 [NOIP2002 提高组] 字串变换题解(双向BFS+记忆化搜索+剪枝)

本题用迭代优先搜索的方法实现了一次。但是的话,相比较而言,双向BFS的方法会更好一些,因为其自带层数,方便判断,向外延伸扩展时也可以用map判重。

这题读来是一道标准的双向BFS模板题,有初末状态,当两边搜索到相交的状态的时候,两者路径之和即为当前路径下的步数。

实现过程中的难点:
1.如何实现双向:弄两个队列,两个转换函数,分别对其进行转化,塞进队列中

#include<cstring>
#include<cstdio>
#include<iostream>
#include<queue>
#include<map>
using namespace std;
struct pel{
	string cur;
	int step;
};
map<string,int>mark;
map<string,char> jud;
queue<pel> q1,q2;
string book1[7],book2[7];
string bgi,edi;
int best=1e6,top=0;
void bfs(){
	pel now1,now2,temp;
	int i,loc;
	now1.cur=bgi,now1.step=0,now2.cur=edi,now2.step=0;
	q1.push(now1),q2.push(now2);
	string next1,next2,tem,tempo;
	
	
	while(true){
		
		if(q1.empty()||q2.empty())break;(有可能两边有剩余的,而部分接头的答案就藏在接头的部分里面)
		
		now1.cur=q1.front().cur,now1.step=q1.front().step,q1.pop();
		if(now1.step+1>10)continue;(大于10直接退出)
		 for(i=1;i<=top;i++){
			 tem=book1[i];
			 loc=now1.cur.find(tem,0);(确定位置在哪)
			 
			for(;loc!=-1;loc=now1.cur.find(tem,loc+1)){
				tempo=now1.cur;(锁定字符串)
				next1=tempo.replace(loc,tem.length(),book2[i]);
			
			if(mark[next1]&&jud[next1]=='b')continue;(如果是自己一头的并且已经找过那么就不用往下搜了(之前的肯定更小))
			if(mark[next1]+now1.step+1>10)continue;(如果目标大于10也中断)
			if(jud[next1]=='e'){(如果接头了就比比大小,然后就不必找了)
			     best=min(best,mark[next1]+now1.step+1);
			     break;
		    }
			if(mark[next1]==0)mark[next1]=1e6;(要是没走过给他个大的值方便下面运行)
			if(mark[next1]>=now1.step+1){
				temp.cur=next1;
				jud[next1]='b';
				temp.step=now1.step+1;
				q1.push(temp);
				mark[next1]=now1.step+1;
			}
		   }
	     }
	    
	    now2.cur=q2.front().cur,now2.step=q2.front().step,q2.pop();
	    if(now2.step+1>10)continue;(这部分和上面部分是一样的)
	    
		 for(i=1;i<=top;i++){
		 	tem=book2[i];
			 loc=now2.cur.find(tem,0);
			 
			for(;loc!=-1;loc=now2.cur.find(tem,loc+1)){
				tempo=now2.cur;
				next2=tempo.replace(loc,tem.length(),book1[i]);
			
			if(mark[next2]&&jud[next2]=='e')continue;
			if(mark[next2]+now2.step+1>10)continue;
			if(jud[next2]=='b'){
	     	best=min(best,mark[next2]+now2.step+1);
		     break; 
	       }
			if(mark[next2]==0)mark[next2]=1e6;
			if(mark[next2]>=now2.step+1){
				temp.cur=next2;
				jud[next2]='e';
				temp.step=now2.step+1;
				q2.push(temp);
				mark[next2]=now2.step+1;
			}
	     }
	     
	    }
	}
}
int main(){
	cin>>bgi>>edi;
	jud[bgi]='b';
	jud[edi]='e';
	string a,b;
	while(top<6&&cin>>a>>b){(读入)
		top++;
		book1[top]=a;
		book2[top]=b;
	}
	
	bfs();
	if(best==1e6)printf("NO ANSWER!");
	 else printf("%d",best);
}

总结:双向BFS模板题,然后的话复习了下字符串函数和结构体队列,加深了对于记忆化搜索的印象(菜菜瑟瑟发抖,写的代码有点臃肿QAQ)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值