2022 Robocom CAIP省赛 第三题 跑团机器人

原题链接:

PTA | 程序设计类实验辅助教学平台

题面:

在桌面角色扮演游戏(TRPG,俗称“跑团”)中,玩家需要掷出若干个骰子,根据掷出的结果推进游戏进度。在线上同样可以跑团,方法是由玩家们向机器人发出指令,由机器人随机产生每个需要掷出的骰子的结果。

玩家向机器人发出的指令是一个仅涉及加法和减法的表达式,即对若干个数字进行一系列加法或减法计算。这些数字可以是直接给出的非负整数(数字不超过 1000),也可以是若干个骰子掷出的结果。

“掷骰子”这个动作对应的指令格式为 xdy,表示摇动 x 个 y 面的骰子(1≤x≤1000,2≤y≤1000)。当 x 为 1 时,1 可以省略。

例如指令 2d3+3-d4 的意思是:先掷出 2 个 3 面骰子(你不必考虑现实中是否存在这样的骰子),不妨假设结果为 1 和 3,则 2d3 的结果就是两个骰子的面值之和 4;然后计算 4 + 3,得到结果为 7;再掷出 1 个 4 面骰子,不妨假设结果为 2,则计算 7 - 2 得到最终结果 5。

本题就请你计算玩家输入的指令里,不同种类的骰子需要掷出几个,以及可能得到的结果在什么区间范围内。

解题思路:

根据题意进行模拟即可,由于只有加减法,所以我们不需要考虑算数优先级,每次计算最大值的时候,加法就假设骰子每个都最大,减法就假设每个骰子都最小,求最小值的时候则反之,注意给出的表达式里边还会有常量;实现方法是从左到右遍历一遍,每次遍历到下一个运算符的时候进行一次计算并且将下一个运算符记录下来。具体实现见代码。

代码(CPP):

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 2e4 + 10;
const int INF = 0x3fffffff;
const int mod = 1000000007;
string s;
ll cnt[maxn];

void solve() {
    cin >> s;
    string tmp = "+";
    int Max = 0, Min = 0;
    for (int i = 0; i <= s.size(); i++) {
        if (i == s.size() || s[i] == '+' || s[i] == '-') {
            int x = 0, y = 0;
            // 将x提取出来
            int j;
            for (j = 1; j < tmp.size(); j++) {
                if (tmp[j] == 'd') {
                    break;
                }
                x = x * 10 + (tmp[j] - '0');
            }

            // 遍历停止位置不是'd',那么代表这是一个常量
            if (tmp[j] != 'd') {
                if (tmp[0] == '-') {
                    Max -= x;
                    Min -= x;
                } else {
                    Max += x;
                    Min += x;
                }
            } else {
                // 题目中说明了,表达式中的x可能被省略,省略则代表x为1
                if (x == 0) {  // 刚开始把这个条件判断写到了“提取x”代码段的后边,这样会导致x如果是常量0,则会被强行改为1
                    x = 1;
                }
                // 将y提取出来
                for (j = j + 1; j < tmp.size(); j++) {
                    y = y * 10 + (tmp[j] - '0');
                }
                cnt[y] += x;
                // Max Min
                if (tmp[0] == '-') {
                    Max -= x;
                    Min -= x * y;
                } else {
                    Max += x * y;
                    Min += x;
                }
            }
            tmp = ""; 
        }
        if (i == s.size()) {
           break;
        }
        tmp += s[i];
    }
    for (int i = 2; i <= 1010; i++) {
        if (cnt[i]) {
            cout << i << " " << cnt[i] << endl;
        }
    }
    cout << Min << " " << Max << endl;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cout << fixed;
    cout.precision(18);

    solve();
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值