AcWing 190 字串变换 双向BFS

#include <bits/stdc++.h>
using namespace std;
const int N = 100;
string A[N], B[N]; //储存变换方式
int cnt;
string st, ed;

int extend_a(queue<string>& q, unordered_map<string, int>& dis)
{
    //对a队列的队首进行拓展
    string t = q.front();
    q.pop();
    int d = dis[t];

    for (int i = 0; i < t.length(); i++) {  //以字符串的每一个字符作为起点尝试所有变换方式
        for (int j = 0; j < cnt; j++) {
            if (t.substr(i, A[j].length()) == A[j]) {
                string ns = t.substr(0, i) + B[j] + t.substr(i + A[j].length());
                if (dis.count(ns) == 0) {
                    q.push(ns);
                    dis[ns] = dis[t] + 1;
                    d = dis[ns];
                }
            }
        }
    }

    return d;
}

int extend_b(queue<string>& q, unordered_map<string, int>& dis)
{
    string t = q.front();
    q.pop();
    int d = dis[t];

    for (int i = 0; i < t.length(); i++) {  //以字符串的每一个字符作为起点尝试所有变换方式
        for (int j = 0; j < cnt; j++) {
            if (t.substr(i, B[j].length()) == B[j]) {
                string ns = t.substr(0, i) + A[j] + t.substr(i + B[j].length());
                if (dis.count(ns) == 0) {
                    q.push(ns);
                    dis[ns] = dis[t] + 1;
                    d = dis[ns];
                }
            }
        }
    }

    return d;
}

int bfs() 
{
    //使用双队列BFS
    unordered_map<string, int> dis_a, dis_b;   //储存到当前状态经历了多少次变换
    queue<string> qa, qb;
    qa.push(st); qb.push(ed);
    dis_a[st] = dis_b[ed] = 0;
    int da = 0, db = 0;          //两端的广搜已经拓展了多少步

    while (!qa.empty() and !qb.empty() and (da + db <= 10) ) {
        if (dis_b.count(qa.front())) {
            //两端的广搜已经相遇
            return dis_a[qa.front()] + dis_b[qa.front()];
        }
        if (dis_a.count(qb.front())) {
            //两端的广搜已经相遇
            return dis_a[qb.front()] + dis_b[qb.front()];
        }
        if (da < db) {
            da = extend_a(qa, dis_a);
        }
        else {
            db = extend_b(qb, dis_b);
        }
        //两端的拓展方向是相反的
    }

    return 11;
}

int main() 
{
#ifndef ONLINE_JUDGE
    freopen("D:/VS CODE/C++/in.txt", "r", stdin);
    freopen("D:/VS CODE/C++/out.txt", "w", stdout);
#endif
    cin >> st >> ed;
    while (cin >> A[cnt] >> B[cnt]) {
        ++cnt;
    }

    if (st == ed) {
        printf("0");
    }

    int ans = bfs();

    if (ans > 10) {
        printf("NO ANSWER!");
    }
    else {
        printf("%d", ans);
    }

    fclose(stdin);
    fclose(stdout);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值