1 条题解
-
0
题意分析
本题是一个石头剪刀布锦标赛的模拟问题,涉及多轮比赛和胜率计算。核心任务是:
-
比赛规则:
- 石头胜剪刀,剪刀胜布,布胜石头,相同则平局。
- 每位玩家与其他所有玩家进行 场比赛,总场次为 。
-
胜率计算:
- 对于每个玩家,胜率定义为 ( w/(w+l) ),其中 ( w ) 为胜场数,( l ) 为败场数。若 ( w+l=0 ),则输出“-”。
解题思路
-
数据结构设计:
- 使用两个数组
w[]
和l[]
分别记录每个玩家的胜场数和败场数。
- 使用两个数组
-
输入处理:
- 循环读取多组测试数据,每组数据包含 ( n ) 和 ( k ),并处理后续的比赛记录。
-
胜负判定:
- 直接比较两个玩家的选择(通过首字母判断),根据石头剪刀布的规则更新胜败数组。
-
结果输出:
- 计算每位玩家的胜率并格式化输出,注意处理未参与比赛的情况(输出“-”)。
示例代码(标准程序)
#include <iostream> #include <stdio.h> #include <string.h> using namespace std; const int N = 100; int w[N], l[N]; int main() { int n, k, flag = 0; while(scanf("%d", &n) == 1 && n) { memset(w, 0, sizeof(w)); memset(l, 0, sizeof(l)); if(flag) printf("\n"); flag = 1; scanf("%d", &k); for(int i = 0; i < k * n * (n - 1) / 2; i++) { int p1, p2; char m1[15], m2[15]; scanf("%d%s%d%s", &p1, m1, &p2, m2); if(m1[0] == m2[0]) continue; if((m1[0] == 'r' && m2[0] == 's') || (m1[0] == 's' && m2[0] == 'p') || (m1[0] == 'p' && m2[0] == 'r')) w[p1]++, l[p2]++; else if((m2[0] == 'r' && m1[0] == 's') || (m2[0] == 's' && m1[0] == 'p') || (m2[0] == 'p' && m1[0] == 'r')) w[p2]++, l[p1]++; } for(int i = 1; i <= n; i++) if(w[i] + l[i]) printf("%.3f\n", (double)w[i] / (l[i] + w[i])); else printf("-\n"); } return 0; }
注意事项
-
输入处理:
- 使用
scanf
而非cin
,因输入量大,scanf
效率更高。 - 测试用例间需输出空行(首行前无空行,后续每组前有一个空行)。
- 使用
-
胜负判定优化:
- 通过比较选择的首字母(
r
、s
、p
)简化逻辑,避免字符串完整比较。
- 通过比较选择的首字母(
-
边界情况:
- 若玩家未参与任何比赛(即 ( w+l=0 )),需输出“-”而非
0.000
。
- 若玩家未参与任何比赛(即 ( w+l=0 )),需输出“-”而非
-
浮点精度:
- 使用
%.3f
确保输出精确到三位小数,自动四舍五入。
- 使用
复杂度分析
- 时间复杂度:( O(k \times n^2) ),其中 ( n ) 为玩家数,( k ) 为每对玩家的比赛次数。
- 空间复杂度:( O(n) ),仅需存储每个玩家的胜败场数。
-
- 1
信息
- ID
- 1654
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者