题目链接

乒乓球

题目描述

给定一串由字符 W(旺仔哥哥得分)和 L(对手得分)组成的比赛记录。需要分别按照11分制和21分制统计比赛结果。

计分规则

  • 在一局比赛中,当某位选手的分数不小于特定值 ),并且双方比分差大于等于 时,该局比赛结束。
  • 如果比赛记录处理完毕时,当前局还未结束,也需要输出当前的比分。
  • 新的一局比赛开始时,比分从 0:0 重新计算。

输出要求

  1. 首先输出所有11分制下的对局比分,每局一行。
  2. 然后输出一个空行。
  3. 最后输出所有21分制下的对局比分,每局一行。

解题思路

本题要求我们根据一份比赛记录,模拟并输出两种不同赛制下的对局结果。由于两种赛制的逻辑完全相同,仅仅是获胜所需的分数阈值 不同(分别为11和21),我们可以设计一个通用的模拟函数来避免代码重复。

通用模拟函数 simulate(record, k) 的逻辑如下

  1. 初始化:定义两个变量,例如 w_scorel_score,用于记录当前局的比分,初始值均为
  2. 遍历记录:逐个字符地读取输入的比赛记录字符串。
    • 如果字符是 W,则 w_score 加 1。
    • 如果字符是 L,则 l_score 加 1。
  3. 判断局点:在每得一分后,都需要检查当前局是否结束。结束条件为:(w_score >= k || l_score >= k) && abs(w_score - l_score) >= 2
    • 如果条件满足,说明一局比赛已打完。此时,我们输出当前的比分 w_score:l_score
    • 输出后,必须将 w_scorel_score 都重置为 ,以便开始下一局的计分。
  4. 处理最终局:当所有字符都处理完毕后,w_scorel_score 中存储的是最后一局的比分。根据题意,这局(如果存在)的比分也需要输出。因此,在循环结束后,我们直接输出 w_score:l_score 即可。

主程序逻辑

  1. 读取完整的比赛记录字符串。
  2. 调用 simulate(record, 11) 来处理并输出11分制的结果。
  3. 输出一个空行。
  4. 调用 simulate(record, 21) 来处理并输出21分制的结果。

代码

#include <iostream>
#include <string>
#include <vector>
#include <cmath>

using namespace std;

void simulate(const string& record, int k) {
    int w_score = 0;
    int l_score = 0;
    for (char c : record) {
        if (c == 'W') {
            w_score++;
        } else {
            l_score++;
        }

        if ((w_score >= k || l_score >= k) && abs(w_score - l_score) >= 2) {
            cout << w_score << ":" << l_score << endl;
            w_score = 0;
            l_score = 0;
        }
    }
    // 输出最后一局(可能未结束)的比分
    cout << w_score << ":" << l_score << endl;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(NULL);

    string record_str;
    string line;
    while(cin >> line) {
        record_str += line;
    }
    
    simulate(record_str, 11);
    cout << endl;
    simulate(record_str, 21);
    
    return 0;
}
import java.util.Scanner;

public class Main {
    
    public static void simulate(String record, int k) {
        int wScore = 0;
        int lScore = 0;
        for (char c : record.toCharArray()) {
            if (c == 'W') {
                wScore++;
            } else {
                lScore++;
            }

            if ((wScore >= k || lScore >= k) && Math.abs(wScore - lScore) >= 2) {
                System.out.println(wScore + ":" + lScore);
                wScore = 0;
                lScore = 0;
            }
        }
        // 输出最后一局(可能未结束)的比分
        System.out.println(wScore + ":" + lScore);
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        StringBuilder sb = new StringBuilder();
        while (sc.hasNext()) {
            String line = sc.next();
            if (line.contains("E")) {
                sb.append(line.substring(0, line.indexOf('E')));
                break;
            }
            sb.append(line);
        }
        
        String record = sb.toString();
        
        simulate(record, 11);
        System.out.println();
        simulate(record, 21);
    }
}
import sys

def simulate(record, k):
    w_score = 0
    l_score = 0
    for char_code in record:
        if char_code == 'E':
            break
        
        if char_code == 'W':
            w_score += 1
        else:
            l_score += 1

        if (w_score >= k or l_score >= k) and abs(w_score - l_score) >= 2:
            print(f"{w_score}:{l_score}")
            w_score = 0
            l_score = 0
            
    # 输出最后一局(可能未结束)的比分
    print(f"{w_score}:{l_score}")

# 读取所有输入直到文件尾
record_str = sys.stdin.read().replace('\n', '')

simulate(record_str, 11)
print()
simulate(record_str, 21)

算法及复杂度

  • 算法:模拟
  • 时间复杂度:设输入记录的总长度为 。我们需要遍历整个记录两次(一次为11分制,一次为21分制),所以总时间复杂度是
  • 空间复杂度:我们只需要常数个变量来存储分数,因此空间复杂度为