题解:学而思编程 划拳
【题目来源】
学而思编程:划拳
【题目描述】
小王和小明在吃饭的时候玩起了划拳游戏。
游戏规则是,每一轮两个人同时说出一个数(只能是 \(5,10,15,20\) 中的一个),若两人说出的数一样,则两人均不计分,否则说出数字更大的人获得两人说出的数差值这么多的分数。
但有一个例外,如果一个人说的 \(20\),但另一个说的是 \(5\) 或 \(10\),则说 \(20\) 的这个人不得分,另一个人得 \(10\) 分。
游戏共进行 \(k\) 轮,求最后两人各自得分。
【输入】
第一行一个整数 \(k\),表示游戏进行的轮数。
接下来 \(k\) 行,每行两个整数分别表示这一轮小王和小明说的数。
【输入】
第一行一个整数 \(k\),表示游戏进行的轮数。
接下来 \(k\) 行,每行两个整数分别表示这一轮小王和小明说的数。
【输出】
一行输出两个整数以空格分开。
分别为小王和小明的得分。
【输入样例】
2
10 15
20 10
【输出样例】
0 15
【核心思想】
-
问题分析:给定 \(k\) 轮划拳数据,每轮两人各出 \(x, y \in \{5, 10, 15, 20\}\)。计分规则分两层:特殊规则(\(20\) 对 \(5/10\) 时出 \(20\) 者不得分,对方得 \(10\) 分)优先于一般规则(数字大者得差值分,相同则不计分)。这是一个规则优先级模拟问题,关键在于特殊规则与一般规则的判定顺序。
-
算法选择:
- 优先级分支:先判定特殊规则(\(20\) 对 \(5/10\)),再判定一般规则(比大小),确保特殊规则优先覆盖
- 逐轮模拟:对每轮输入直接计算得分,无需存储历史数据
-
关键步骤:
- 初始化:\(a = 0\)(小王得分),\(b = 0\)(小明得分)
- 逐轮处理(循环 \(k\) 次):
- 读取 \(x\)(小王出的数)、\(y\)(小明出的数)
- 特殊规则判定(优先检查):
- 若 \(x = 20\) 且 \((y = 5\) 或 \(y = 10)\):\(b \leftarrow b + 10\)(小王出 \(20\) 但对方出 \(5/10\),小王不得分,小明得 \(10\) 分)
- 否则若 \(y = 20\) 且 \((x = 5\) 或 \(x = 10)\):\(a \leftarrow a + 10\)(小明出 \(20\) 但小王出 \(5/10\),小明不得分,小王得 \(10\) 分)
- 一般规则判定(特殊规则不满足时):
- 若 \(x > y\):\(a \leftarrow a + (x - y)\)
- 否则(此时 \(x \le y\),由题意 \(x \neq y\) 已排除相等):\(b \leftarrow b + (y - x)\)
- 输出结果:输出 \(a\) 和 \(b\)
-
时间/空间复杂度:
- 时间复杂度:\(O(k)\),每轮 \(O(1)\) 判定,共 \(k\) 轮
- 空间复杂度:\(O(1)\),仅使用 \(a\)、\(b\) 两个累加器
-
规则优先级模拟的核心思想:
- 特殊优先原则:特殊规则(\(20\) 对 \(5/10\))必须优先于一般规则判定。若先判定一般规则,\(20 > 10\) 会使出 \(20\) 者得 \(10\) 分,与特殊规则矛盾。使用
if-else if结构确保互斥执行 - 对称处理:特殊规则对双方对称,分别检查 \(x=20\) 对方为 \(5/10\) 和 \(y=20\) 对方为 \(5/10\) 两种情况
- 一般规则简化:特殊规则排除后,一般规则只需比较 \(x\) 与 \(y\) 大小,差值即为得分。相等时自然不得分(差值为 \(0\)),无需额外判断
- 在线累加:边读入边计算,无需存储每轮结果,节省空间
- 适用于游戏规则模拟、多优先级条件判定类问题
- 特殊优先原则:特殊规则(\(20\) 对 \(5/10\))必须优先于一般规则判定。若先判定一般规则,\(20 > 10\) 会使出 \(20\) 者得 \(10\) 分,与特殊规则矛盾。使用
【算法标签】
模拟
【代码详解】
#include <bits/stdc++.h>
using namespace std;
int a, b, k;
int main()
{
cin >> k;
for (int i = 1; i <= k; i++)
{
int x, y;
cin >> x >> y;
// 特殊规则:当一方为20,另一方为5或10时
if (x == 20 && (y == 5 || y == 10))
{
b += 10; // 玩家b获得10分
}
else if (y == 20 && (x == 5 || x == 10))
{
a += 10; // 玩家a获得10分
}
else
{
// 一般规则:分数高的一方获得差值分数
if (x > y)
{
a += x - y; // 玩家a获得差值
}
else
{
b += y - x; // 玩家b获得差值
}
}
}
cout << a << " " << b << endl;
return 0;
}
【运行结果】
2
10 15
20 10
0 15
浙公网安备 33010602011771号