题解:P1032 [NOIP 2002 提高组] 字串变换
题目链接:link。
为了高效地解决这道题目,我们考虑使用双向搜索解决。
我们从 \(A\) 和 \(B\) 同时开始搜索,要是中间有相遇,那么就说明 \(A\) 能变成 \(B\) 这样我们就结束搜索,在搜索的过程中,我们还需要记录 \(A\) 变成 \(B\) 的步数,如果步数小于等于 \(10\) 那么就说明这样可以。其他情况就都输出 NO ANSWER! 就行了。
在双向搜索的过程中,我们每次选取长度短的字符进行单向搜索判断是否可以和另外一个字符串重合。
大体思路就这些,接下来上代码:
#include<bits/stdc++.h>
#define I using
#define AK namespace
#define IOI std
#define i_ak return
#define ioi 0
#define i_will signed
#define ak main
#define IMO ()
I AK IOI;
string A,B;
vector<pair<string,string> >front,back;
queue<string>st,en;
unordered_map<string,int>sts,ens;
vector<string> ff(const string&s,const string&a,const string&b){
vector<string>res;
if(a.empty())return res;
size_t pos=0;
while(pos<=s.size()-a.size()){
size_t found=s.find(a,pos);
if(found==string::npos)break;
string new_=s.substr(0,found)+b+s.substr(found+a.size());
res.push_back(new_);
pos=found+1;
}
return res;
}
int f(queue<string>&q,unordered_map<string,int>&step,unordered_map<string,int>&step2,vector<pair<string,string>>&r){
int len=q.size();
for(int i=0;i<len;i++){
string s=q.front();
q.pop();
int step_=step[s];
if(step_>=10)continue;
for(auto&it:r){
vector<string>next=ff(s,it.first,it.second);
for(string&it_:next){
if(!step.count(it_)){
step[it_]=step_+1;
q.push(it_);
if(step2.count(it_)){
int tot=step_+1+step2[it_];
if(tot<=10)return tot;
}
}
}
}
}
return -1;
}
void bfs(){
st.push(A);
sts[A]=0;
en.push(B);
ens[B]=0;
int ans=-1;
while(!st.empty()&&!en.empty()){
if(st.size()<=en.size()){
int step=f(st,sts,ens,front);
if(step!=-1){
ans=step;
break;
}
}
else{
int steps=f(en,ens,sts,back);
if(steps!=-1){
ans=steps;
break;
}
}
}
if(ans!=-1&&ans<=10)cout<<ans;
else puts("NO ANSWER!");
}
i_will ak IMO{
cin>>A>>B;
if(A==B){
puts("0");
i_ak ioi;
}
string a,b;
while(cin>>a>>b){
front.push_back({a,b});
back.push_back({b,a});
}
bfs();
i_ak ioi;
}
亲测可过,请勿抄袭!

浙公网安备 33010602011771号