字串变换(字符串+搜索剪枝)

题意:将一个字符串从初始状态变换为目标状态,最多有6种变换规则,如果10步之内能完成,输出步数.

分析:又是一道有关字符串的搜索题,思路很简单,把初始状态放入队列里开始跑广搜,枚举所有变换规则,能变就变,变完就入队,队列为空和步数超过10都表示不能完成变换任务.稍微剪下枝就可以了.

int num=1;
string a,b,turna[7],turnb[7];
queue<string> Q;
queue<int> ans;
map<string,int> visit;
bool bfs(){
    while(Q.size()&&Q.front()!=b&&ans.front()<=10){
//如果队列里还有元素,且还没达到目标状态,且步数小于10
		if(visit[Q.front()]){
	    	Q.pop();ans.pop();
	    	continue;
		}//剪枝:如果之前这个状态搜索过,就跳过
//枚举num中变换规则:
		for(int i=1;i<=num;i++){
	    	string s1=Q.front();
	    	visit[s1]=1;
	    	while(1){
				int pos=s1.find(turna[i]);
//在要被变换的字符串s1中找是否有可以变换的子串
				if(pos==-1)break;
//找不到就退出,找得到就对s2开始进行变换:
				string s2=Q.front();
				s2.replace(pos,turna[i].size(),turnb[i]);
//熟悉字符串replace的用法:
//从字符串s2的pos下标起,长度为turna[i].size()
//变换为turnb[i]
				Q.push(s2);//变换后入队
				ans.push(ans.front()+1);
				s1[place]='|';
//将s1里子串turna[i]的这次出现位置随便换成另一种字符
//这样就可以查找到s1里子串turna[i]的下一个出现位置
	    	}
		}
		Q.pop();ans.pop();
    }
    if(!Q.size()||ans.front()>10)return 0;
    return 1;
}
int main(){
    cin>>a>>b;
    Q.push(a);//初始状态入队
    ans.push(0);//初始状态步数为0
//Q队列和ans队列里面的元素一一对应.
    while(cin>>turna[num]>>turnb[num])num++;
    num--;
//读入num种变换规则
    int pd=bfs();
    if(!pd) puts("NO ANSWER!");
    else printf("%d\n",ans.front());
    return 0;
}

posted on 2019-01-29 21:44  PPXppx  阅读(104)  评论(0编辑  收藏  举报