详细的代码注释!
参考代码:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 6;
string a[N], b[N], A, B;
int n;
int extend(queue<string>& q, unordered_map<string, int>& da, unordered_map<string, int>& db, string a[], string b[]){
// 每次每边扩展完整一层:由于队列最多保留两层!
// 由于拓展一个点可能会导致最优解被漏掉,因此应该拓展一层!
// y总解释:https://www.acwing.com/activity/content/code/content/132167/
for(int k = 0, sk = q.size(); k < sk; k ++){
auto t = q.front();
q.pop();
// 各种规则进行匹配
for(int i = 0; i < t.size(); i ++)
for(int j = 0; j < n; j ++)
if(t.substr(i, a[j].size()) == a[j]){ // 从该串从前向后扫描看是否匹配该a[j]规则
// 拼串
string status = t.substr(0, i) + b[j] + t.substr(i + a[j].size());
// 下方两个判断可以互换!
// 若另一个队列已经搜到该状态,则表示已找到最优解
if(db.count(status)) return da[t] + 1 + db[status];
// 若当前队列已经搜过该状态,直接continue
if(da.count(status)) continue;
da[status] = da[t] + 1;
q.push(status);
}
}
// 否则说明当前状态使用所有规则仍然无法与另一个队列相遇得到最优解
return 11;
}
int bfs(){
queue<string> qa, qb;
unordered_map<string, int> da, db;
qa.push(A), da[A] = 0;
qb.push(B), db[B] = 0;
while(qa.size() && qb.size()){
int t;
// 优先拓展队列少的一侧
if(qa.size() <= qb.size()) t = extend(qa, da, db, a, b);
else t = extend(qb, db, da, b, a); // 反向队列db与da要反一下,a与b也要反一下!
// 这里的t有几种情况:
// 1. 拓展后,两队列无法相遇,仍需进一步bfs
// 2. 拓展后,两队列相遇,总步数大于10,仍需进一步bfs
// 3. 拓展后,两队列相遇,总步数小于等于10,则已得到最优解,直接返回
if(t <= 10) return t;
}
// 遍历完所有情况,仍无法相遇,则说明无解!
return 11;
}
int main(){
cin >> A >> B;
while(cin >> a[n] >> b[n]) n ++;
int step = bfs();
if(step > 10) cout << "NO ANSWER!" << endl;
else cout << step << endl;
return 0;
}