【题解】P1032 字串变换

题面

题目传送门

前言

字符串简单处理 + 迭代加深搜索

正文

本题一眼搜索

题解区好像都是广搜(或者 meet in the middle 之类的)

云落不大喜欢 BFS,所有我们选择 DFS

题意要求我们去求一个最小变换次数,即搜索树上的最小深度

很容易想到迭代加深搜索

若干个难点:

  1. 区别于朴素的迭代加深搜索,这个题的状态拓展是在字符串上进行的,所以与状态相关的信息的存储需要由数组转化为映射,云落使用的 map,(手写哈希也可嗷!)

  2. 剪枝优化

  • 迭代加深搜索自行控制深度——可行性剪枝

  • 当字符串相同时,停止搜索,记录答案最小值——边界条件(最优性剪枝)

  • 当一个状态已经被访问过,且当前答案不优于已有的答案,直接减掉——最优性剪枝

  1. 状态拓展
  • 若干个字符串操作

  • 请注意:find 函数只能找到一个合法的子串,我们需要人为规定一下找子串的范围

  1. 迭代加深终止条件:if(ans!=inf)break;

代码

#include<iostream>
#include<cstdio>
#include<string>
#include<algorithm>
#include<map>
using namespace std;
const int maxn=8,inf=2147483647;
string A,B;
struct Edge{
	string u,v;
}e[maxn];
int tot=1,ans=inf,dep=2;
map<string,bool> vis;
map<string,int> dis;
inline void dfs(string str,int stp){
	if(stp>dep){
		return;
	}
	if(str==B){
		ans=min(ans,stp);
		return;
	}
	if(vis[str]){
		if(stp>=dis[str]){
			return;
		}
	}
	vis[str]=true;
	dis[str]=stp;
	for(int i=1;i<=tot;i++){
		int idx=-1;
		while(true){
			idx=str.find(e[i].u,idx+1);
			if(idx==-1){
				break;
			}
			string tmp=str;
			tmp.erase(idx,e[i].u.length());
			tmp.insert(idx,e[i].v);
			dfs(tmp,stp+1);
		}
	}
	return;
}
int main(){
	cin>>A>>B;
	while(cin>>e[tot].u>>e[tot].v){
		tot++;
	}
	tot--;
	while(true){
		if(ans!=inf){
			break;
		}
		dfs(A,0);
		dis.clear();
		vis.clear();
		dep++;
		if(dep==11){
			break;
		}
	}
	if(ans==inf){
		cout<<"NO ANSWER!"<<endl;
		return 0;
	}
	cout<<ans<<endl;
	return 0;
}

后记

哎,居然是个绿题,稍稍恶心了一下下呢!

完结撒花!

posted @ 2025-01-01 13:51  sunxuhetai  阅读(20)  评论(0)    收藏  举报