成语接龙游戏

题目信息

小张非常喜欢与朋友们玩成语接龙的游戏,但是作为“文化沙漠”的小张,成语的储备量有些不足。现在他的大脑中存储了 m 个成语,成语中的四个汉字都用一个1000000以内的正整数来表示。现在小张的同学为了考验他给出了他一个成语做开头和一个成语做结尾,如果小张能通过成语接龙的方式说到结尾的成语,他就能够成功完成游戏。他想知道最少能说几个成语能够成功完成游戏。

输入

第一行一个数 m(1 ≤ m ≤ 300000 )
接下来 m 行,每行4个1000000以内的正整数,表示一个成语。
下一行4个1000000以内的正整数,表示开始成语。
下一行4个1000000以内的正整数,表示结束成语。
保证开始成语和结束成语在小张的成语储备之中。

输出

一行一个整数,表示最少说几个成语能够完成游戏。如果无法完成输出-1。

提示

三个成语分别是(1,2,3,4)(4,5,6,7)(7,8,9,10)

测试样例

测试样例1

5
1 2 3 4
4 5 6 7
7 8 9 10
4 6 6 1
1 6 8 8
1 2 3 4
7 8 9 10
3

测试样例2

5
1 2 3 4
4 5 6 7
7 8 9 10
4 6 6 1
1 6 8 8
1 2 3 4
1 2 3 4
1

解答

#include <bits/stdc++.h>

using namespace std;

struct BiaoJi
{
    long ChengYu;
    bool visit;

    BiaoJi(long ChengYu_, bool visit_)
    {
        ChengYu = ChengYu_;
        visit = visit_;
    }
};

vector<BiaoJi> g[300000 + 10];

struct Pos
{
public:
    long id;
    long step;

    Pos(long id_, long step_) : id(id_), step(step_)
    {}
};

struct ChengYu
{
public:
    long ChengYuA;
    long ChengYuB;
    long ChengYuC;
    long ChengYuD;
};

queue<Pos> q;

int main()
{
    //freopen("E://test.txt", "r", stdin);
    long m;
    cin >> m;
    for (long i = 0; i < m; i++)
    {
        ChengYu tmp;
        cin >> tmp.ChengYuA >> tmp.ChengYuB >> tmp.ChengYuC >> tmp.ChengYuD;
        g[tmp.ChengYuA].push_back(BiaoJi(tmp.ChengYuD, 0));//以成语第一个字作为横坐标来存储成语,记录着每一个开头的成语都能走到哪里去
    }

    ChengYu ChengYustart, ChengYuend;
    cin >> ChengYustart.ChengYuA >> ChengYustart.ChengYuB >> ChengYustart.ChengYuC >> ChengYustart.ChengYuD
        >> ChengYuend.ChengYuA >> ChengYuend.ChengYuB >> ChengYuend.ChengYuC >> ChengYuend.ChengYuD;
    if (ChengYustart.ChengYuA == ChengYuend.ChengYuA && ChengYustart.ChengYuB == ChengYuend.ChengYuB &&
        ChengYustart.ChengYuC == ChengYuend.ChengYuC && ChengYustart.ChengYuD == ChengYuend.ChengYuD)
    {//相等的情况
        cout << 1 << endl;
        return 0;
    }
    if (ChengYustart.ChengYuD == ChengYuend.ChengYuA)
    {//开头成语和结尾成语恰好能连上
        cout << 2 << endl;
        return 0;
    }
    Pos PosStart(ChengYustart.ChengYuD, 0);
    q.push(PosStart);
    long MIN = 300000 + 10;
    while (!q.empty())
    {
        Pos tmp = q.front();
        for (long i = 0; i < g[tmp.id].size(); i++)
        {//遍历这一行vector
            if (g[tmp.id][i].visit == 0)
            {//没有访问过
                if (g[tmp.id][i].ChengYu == ChengYuend.ChengYuA)
                {
                    if (tmp.step + 3 <= MIN)
                    {
                        MIN = tmp.step + 3;
                    }
                }
                g[tmp.id][i].visit = 1;
                Pos ReturnPos(g[tmp.id][i].ChengYu, tmp.step + 1);
                q.push(ReturnPos);
            }
        }
        q.pop();
    }
    if (MIN != 300000 + 10)
    {
        cout << MIN << endl;
    }
    else
    {
        cout << -1 << endl;
    }
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhj12399

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值