团体程序设计天梯赛-练习集-L2-040 哲哲打游戏 (25 分)

哲哲是一位硬核游戏玩家。最近一款名叫《达诺达诺》的新游戏刚刚上市,哲哲自然要快速攻略游戏,守护硬核游戏玩家的一切!

为简化模型,我们不妨假设游戏有 N 个剧情点,通过游戏里不同的操作或选择可以从某个剧情点去往另外一个剧情点。此外,游戏还设置了一些存档,在某个剧情点可以将玩家的游戏进度保存在一个档位上,读取存档后可以回到剧情点,重新进行操作或者选择,到达不同的剧情点。

为了追踪硬核游戏玩家哲哲的攻略进度,你打算写一个程序来完成这个工作。假设你已经知道了游戏的全部剧情点和流程,以及哲哲的游戏操作,请你输出哲哲的游戏进度。

输入格式:

输入第一行是两个正整数 N 和 M (1≤N,M≤105),表示总共有 N 个剧情点,哲哲有 M 个游戏操作。

接下来的 N 行,每行对应一个剧情点的发展设定。第 i 行的第一个数字是 Ki​,表示剧情点 i 通过一些操作或选择能去往下面 Ki​ 个剧情点;接下来有 Ki​ 个数字,第 k 个数字表示做第 k 个操作或选择可以去往的剧情点编号。

最后有 M 行,每行第一个数字是 0、1 或 2,分别表示:

  • 0 表示哲哲做出了某个操作或选择,后面紧接着一个数字 j,表示哲哲在当前剧情点做出了第 j 个选择。我们保证哲哲的选择永远是合法的。
  • 1 表示哲哲进行了一次存档,后面紧接着是一个数字 j,表示存档放在了第 j 个档位上。
  • 2 表示哲哲进行了一次读取存档的操作,后面紧接着是一个数字 j,表示读取了放在第 j 个位置的存档。

约定:所有操作或选择以及剧情点编号都从 1 号开始。存档的档位不超过 100 个,编号也从 1 开始。游戏默认从 1 号剧情点开始。总的选项数(即 ∑Ki​)不超过 106。

输出格式:

对于每个 1(即存档)操作,在一行中输出存档的剧情点编号。

最后一行输出哲哲最后到达的剧情点编号。

输入样例:

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

输出样例:

1
3
9
10

样例解释:

简单给出样例中经过的剧情点顺序:

1 -> 4 -> 3 -> 7 -> 8 -> 3 -> 5 -> 9 -> 10。

档位 1 开始存的是 1 号剧情点;档位 2 存的是 3 号剧情点;档位 1 后来又存了 9 号剧情点。

看不懂的错误:

这题我刚开始在做的时候,将存档和经过的剧情点都用了vector来存储,在提交时发现报了莫名其妙的段错误:

部分错误代码示例:

#include <iostream>
#include <vector>
using namespace std;

const int N = 100000;  //剧情点数和操作数的最大值
vector<int> v[N + 1];
vector<int> ans, archive;  //结果和存档

int main() {
    int n, m;  //n个剧情点,m个操作
    cin >> n >> m;
    for (int i = 1; i <= n; i++) {
        int k;  //可去往的剧情点数
        cin >> k;
        while (k--) {
            int x;
            cin >> x;
            v[i].push_back(x);
        }
    }
    ans.push_back(1);
    for (int i = 0; i < m; i++) {
        int c, j;
        cin >> c >> j;
        if (c == 0) {
            ans.push_back(v[ans.back()][j - 1]);
        } else if (c == 1) {
            archive.push_back(ans.back());
        } else {
            ans.push_back(archive[j - 1]);
        }
    }
    for (auto i : archive) {
        cout << i << endl;
    }
    cout << ans.back() << endl;
    return 0;
}

检查不出原因,寻思可能是vector的问题,于是我直接把存档的vector换成了普通数组,经过的剧情点直接不予存储,只记录当前的剧情点,更改完后果然全部都正确了,可恶!

正确代码示例:

#include <iostream>
#include <vector>
using namespace std;

const int N = 100000;  //剧情点数和操作数的最大值
vector<int> v[N + 1];  //存放剧情点发展
int archive[101];      //存档
int cur = 1;           //当前剧情点

int main() {
    int n, m;  //n个剧情点,m个操作
    cin >> n >> m;
    for (int i = 1; i <= n; i++) {
        int k;  //可去往的剧情点数
        cin >> k;
        while (k--) {
            int x;
            cin >> x;
            v[i].push_back(x);
        }
    }
    while (m--) {
        int c, j;
        cin >> c >> j;
        if (c == 0) {
            cur = v[cur][j - 1];  //当前剧情点更新
        } else if (c == 1) {
            archive[j] = cur;  //存档
            cout << archive[j] << endl; 
        } else {
            cur = archive[j];  //读取存档
        }
    }
    cout << cur << endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

月初XH

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

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

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

打赏作者

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

抵扣说明:

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

余额充值