[普及][NOIP2003 普及组] 乒乓球

这篇博客介绍了如何分析乒乓球比赛数据,特别是在1111分制和2121分制下计算比赛结果。博主提供了多种思路和AC代码,强调在处理比赛记录时需要存储胜负顺序,并确保分差大于2才能结束一局。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目背景

国际乒联现在主席沙拉拉自从上任以来就立志于推行一系列改革,以推动乒乓球运动在全球的普及。其中 1111 分制改革引起了很大的争议,有一部分球员因为无法适应新规则只能选择退役。华华就是其中一位,他退役之后走上了乒乓球研究工作,意图弄明白 1111 分制和 2121 分制对选手的不同影响。在开展他的研究之前,他首先需要对他多年比赛的统计数据进行一些分析,所以需要你的帮忙。

题目描述

华华通过以下方式进行分析,首先将比赛每个球的胜负列成一张表,然后分别计算在 1111 分制和 2121 分制下,双方的比赛结果(截至记录末尾)。

比如现在有这么一份记录,(其中 WW 表示华华获得一分,LL 表示华华对手获得一分):

WWWWWWWWWWWWWWWWWWWWWWLWWWWWWWWWWWWWWWWWWWWWWWLW

在 1111 分制下,此时比赛的结果是华华第一局 1111 比 00 获胜,第二局 1111 比 00 获胜,正在进行第三局,当前比分 11 比 11。而在 2121 分制下,此时比赛结果是华华第一局 2121 比 00 获胜,正在进行第二局,比分 22 比 11。如果一局比赛刚开始,则此时比分为 00 比 00。直到分差大于或者等于 22,才一局结束。

你的程序就是要对于一系列比赛信息的输入(WLWL 形式),输出正确的结果。

输入格式

每个输入文件包含若干行字符串,字符串有大写的 WW 、 LL 和 EE 组成。其中 EE 表示比赛信息结束,程序应该忽略 EE 之后的所有内容。

输出格式

输出由两部分组成,每部分有若干行,每一行对应一局比赛的比分(按比赛信息输入顺序)。其中第一部分是 1111 分制下的结果,第二部分是 2121 分制下的结果,两部分之间由一个空行分隔。

样例 #1

样例输入 #1

WWWWWWWWWWWWWWWWWWWW
WWLWE

Copy

样例输出 #1

11:0
11:0
1:1

21:0
2:1

Copy

提示

每行至多 25 个字母,最多有 2500 行。

(注:事实上有一个测试点有 2501 行数据。)

题解1

思路

首先一定要开数组存胜负

因为你不仅要存胜负的场数,还要存胜负的顺序,以此来排分数。

玩过乒乓球大部分人都知道,正规乒乓球比赛,不仅分数要大于11(或21),两者分数相差也要大于2。

如果比赛分数达到11-10,比赛会继续。直到一个人比另外一个人多两分。

21分制同理

我是把输入、11分制、21分制一起记录,毕竟一个函数。只开了一个数组。初始值为0(开全局变量),当录到W赋值1(胜),录到L赋值2(负)。方便下面取用。

取用时,读到1,胜数++,读到二,负数++,按照上文判定来输出,读到0,表明记录结束了,输出之前剩余的分数即可。

简洁版:

  • 要么一次性读取数据后面再慢慢判断
  • 要么边输入边判断两种情况,不过答案要先存起来

AC代码

#include<bits/stdc++.h> 
using namespace std;
char str[1000001], a;
int cnt=0;
void ccl(int n)
{
    int a=0,b=0;
    for(int i=1;i<=cnt;i++)
    {
        if(str[i]=='W')
        {
            a++;
        }
        if(str[i]=='L')
        {
            b++;
        }
        if((a>=n||b>=n)&&abs(a-b)>=2)
        {
            cout<<a<<":"<<b<<endl;
            a=b=0;
        }
    }
    cout<<a<<":"<<b<<endl;
    return;
}
int main()
{
    while(cin>>a&&a!='E')
    {
        if(a=='W'||a=='L')
        {
            cnt++; 
            str[cnt]=a;
        }
    }
    ccl(11);
    cout<<endl;
    ccl(21);
    return 0;
}

题解2

这道题也是模拟,我们可以在输入时模拟进球比分,在比分满足条件(这里吐槽一下,题目里也没说清楚,是在一方≥11≥11分且分差≥2≥2分才下一局)时因为输出格式的要求,加入vector。 最后遍历vector输出就可以了:

#include <bits/stdc++.h>
using namespace std;
int W1, L1, W2, L2;
char ch;
vector<int> c1, c2, c3, c4;
int main()
{
    do // 我这里用了do-while
    {
        ch = getchar(); // scanf("%c", &ch);
        if (ch == 'W')
        { 
            // 11分和21分都++
            W1++;
            W2++;
        }
        if (ch == 'L')
        {
            L1++;
            L2++;
        }
        if ((W1 >= 11 || L1 >= 11) && abs(W1 - L1) >= 2)
        {
            c1.push_back(W1);
            c2.push_back(L1);
            W1 = 0; // 记得归0
            L1 = 0;
        }
        if ((W2 >= 21 || L2 >= 21) && abs(W2 - L2) >= 2)
        {
            c3.push_back(W2);
            c4.push_back(L2);
            W2 = 0;
            L2 = 0;
        }
    } while (ch != 'E'); // 注意分号
    // 按格式输出
    for (int i = 0; i < c1.size(); i++)
    {
        printf("%d:%d\n", c1[i], c2[i]);
    }
    printf("\n");
    for (int i = 0; i < c3.size(); i++)
    {
        printf("%d:%d\n", c3[i], c4[i]);
    }
    return 0;
}

Copy

然后…………

恭喜您获得0分的好成绩! 我们观察一下,会发现只有在循环中完成一局才会push_back,但是如果结束了而不满一局,则不会加到vector中。我们补上:

#include <bits/stdc++.h>
using namespace std;
int W1, L1, W2, L2;
char ch;
vector<int> c1, c2, c3, c4;
int main()
{
    do
    {
        ch = getchar(); // scanf("%c", &ch);
        if (ch == 'W')
        {
            W1++;
            W2++;
        }
        if (ch == 'L')
        {
            L1++;
            L2++;
        }
        if ((W1 >= 11 || L1 >= 11) && abs(W1 - L1) >= 2)
        {
            c1.push_back(W1);
            c2.push_back(L1);
            W1 = 0;
            L1 = 0;
        }
        if ((W2 >= 21 || L2 >= 21) && abs(W2 - L2) >= 2)
        {
            c3.push_back(W2);
            c4.push_back(L2);
            W2 = 0;
            L2 = 0;
        }
    } while (ch != 'E'); // ;
    // 增加尾分
    c1.push_back(W1);
    c2.push_back(L1);
    c3.push_back(W2);
    c4.push_back(L2);
    for (int i = 0; i < c1.size(); i++)
    {
        printf("%d:%d\n", c1[i], c2[i]);
    }
    printf("\n");
    for (int i = 0; i < c3.size(); i++)
    {
        printf("%d:%d\n", c3[i], c4[i]);
    }
    return 0;
}

Copy

0分和100分的差距~

��AC ����Code

#include <bits/stdc++.h>
using namespace std;
int W1, L1, W2, L2;
char ch;
vector<int> c1, c2, c3, c4;
int main()
{
    do
    {
        ch = getchar(); // scanf("%c", &ch);
        if (ch == 'W')
        {
            W1++;
            W2++;
        }
        if (ch == 'L')
        {
            L1++;
            L2++;
        }
        if ((W1 >= 11 || L1 >= 11) && abs(W1 - L1) >= 2)
        {
            c1.push_back(W1);
            c2.push_back(L1);
            W1 = 0;
            L1 = 0;
        }
        if ((W2 >= 21 || L2 >= 21) && abs(W2 - L2) >= 2)
        {
            c3.push_back(W2);
            c4.push_back(L2);
            W2 = 0;
            L2 = 0;
        }
    } while (ch != 'E');
    c1.push_back(W1);
    c2.push_back(L1);
    c3.push_back(W2);
    c4.push_back(L2);
    for (int i = 0; i < c1.size(); i++)
    {
        printf("%d:%d\n", c1[i], c2[i]);
    }
    printf("\n");
    for (int i = 0; i < c3.size(); i++)
    {
        printf("%d:%d\n", c3[i], c4[i]);
    }
    return 0;
}

 题解3

下面发一个我做的代码吧。个人感觉思路很明确。看一遍基本上就懂了(吧?)

首先一定要开数组存胜负

因为你不仅要存胜负的场数,还要存胜负的顺序,以此来排分数。

其次分数差要大于2。

玩过乒乓球大部分人都知道,正规乒乓球比赛,不仅分数要大于11(或21),两者分数相差也要大于2。如果比赛分数达到11-10,比赛会继续。直到一个人比另外一个人多两分。(如13-11)

21分制同理

搞完这些重点说思路

我的思路没有DALAO们这么~复杂~优秀。我是把输入、11分制、21分制分而治之。只开了一个数组。初始值为0(开全局变量),当录到W赋值1(胜),录到L赋值2(负)。方便下面取用。

取用时,读到1,胜数++,读到二,负数++,按照上文判定来输出,读到0,表明记录结束了,输出之前剩余的分数即可。

下面是本蒟蒻的代码

`

//stone_juice石汁 P1042 乒乓球
#include <iostream>
#include <cstring>
using namespace std;
int win[62503]; 
int w,l;
int main()
{
	char s;
	for(int i=1;cin>>s&&s!='E';i++)//循环读入,当读到字符E结束 
	{
		if(s=='W')win[i]=1; 
		else win[i]=2; 
	}
	//----------------11分制 ----------------
	for(int i=1;1;i++)
	{
		if(win[i]==1)w++;//胜场+1 
		if(win[i]==2)l++;//负场+1 
		if(win[i]==0)//读到0则记录结束,输出记录结束前的分数。 
		{
			cout<<w<<":"<<l<<endl<<endl;
			break;
		}
		if(w-l>=2||l-w>=2)
			if(w>=11||l>=11)//当双方比分相差大于2且一方分数大等于11输出 
			{
				cout<<w<<":"<<l<<endl;
				w=0;//比分清零 
				l=0;
			}
	}
	w=0;//清零,为21分制计算做准备 
	l=0;
	//----------------21分制 ----------------
	for(int i=1;1;i++)//一切同上,唯一区别就是判定从11变为21 
	{
		if(win[i]==1)w++;
		if(win[i]==2)l++;
		if(win[i]==0)
		{
			cout<<w<<":"<<l;
			break;
		}
		if(w-l>=2||l-w>=2)
			if(w>=21||l>=21)//11变为21 
			{
				cout<<w<<":"<<l<<endl;
				w=0;
				l=0;
			}
	}
	return 0;//华丽地结束  ㄟ(▔▽▔)ㄏ
}
<think>好的,我现在需要给用户介绍一下题目A,也就是NOIP2003普及组的“乒乓球”问题。首先,我得回忆一下这个题目的具体内容,可能涉及到的问题描述、输入输出格式以及解题思路。 首先,题目大意应该是关于乒乓球比赛的比分规则。根据NOIP的题目特点,这应该是一个模拟题,需要处理比赛结果的数据,然后输出正确的结果。可能涉及到的是根据给定的比赛记录,分别统计11分制和21分制下的比赛结果,比如每局比分,总局数等。 接下来,我需要确定用户的需求是什么。用户可能希望了解这个题目的背景、输入输出要求,以及如何解决这个问题。他们可能是一个刚开始学习编程的学生,或者正在准备NOIP竞赛,需要理解这个问题的解决思路。 那么,我应该先简要介绍题目背景,说明乒乓球比赛的两种赛制(11分制和21分制),然后详细描述输入输出的格式。例如,输入可能是一系列比赛的结果,用字符表示,比如'W'代表华华赢,'L'代表对手赢,'E'表示结束。输出则是分别按照两种赛制输出每局的比分,以及获胜的局数。 接下来需要考虑解题思路。这个问题应该如何处理输入数据?可能需要逐个字符读取,直到遇到'E'。然后,分别模拟两种赛制下的比赛过程。对于11分制和21分制,判断一局结束的条件是某一方达到11或21分,并且领先对方至少2分。否则需要继续比赛直到满足条件。 在具体实现上,可能需要两个函数或两个循环来处理两种赛制。对于每一分,需要更新当前局的比分,并检查是否满足结束条件。当一局结束后,将比分记录下来,并重置当前比分,开始下一局。最后,输出所有局的比分,以及可能未完成的当前局比分(如果有的话)。 需要注意的细节包括:输入可能有多行,直到遇到'E'为止;输入中可能包含除W、L、E之外的其他字符,需要忽略;在输出时,每局的结果以比分的形式呈现,比如21:19,每行一个结果,先输出11分制的结果,再输出21分制的。 可能的错误点包括:没有正确处理领先2分的条件,或者在处理输入时遗漏了某些字符。例如,当比分达到10:10时,必须继续比赛直到一方领先两分才能结束该局。 举个例子,假设输入的记录是WWWWWWWWWWWE,那么在11分制下,华华以11:0赢下一局,而在21分制下也是21:0赢一局。如果记录是WLWLLWLLWLWLWE,可能需要计算每个赛制下的比分情况。 总结步骤应该是:读取输入,处理两种赛制,模拟比赛过程,记录每局比分,最后按要求输出。需要分步骤讲解,确保用户理解每一步的逻辑。 可能用户还会关心如何测试自己的程序是否正确,可以建议他们用题目给出的样例输入,或者自己构造一些边界情况,比如刚好赢2分的情况,或者需要多局的情况。 最后,提醒用户注意代码实现的细节,比如字符处理的方式,循环终止条件,以及输出格式的正确性。</think>**题目 A. [NOIP2003 普及组] 乒乓球** 这是一道模拟题,要求根据乒乓球比赛的得分记录,分别按 **11 分制** 和 **21 分制** 的规则统计每局比分。 --- ### **题目背景** 乒乓球比赛的胜负规则如下: - 一局比赛中,先得 **11 分**(或 **21 分**)且领先对手至少 **2 分** 的一方获胜。 - 若比分达到 10:10(或 20:20),则需继续比赛,直到一方领先 2 分为止。 - 输入为一系列比赛记录(由 `W`、`L`、`E` 组成),需输出两种赛制下的每局比分。 --- ### **输入格式** - 输入包含若干行字符串,仅由 `W`(华华得分)、`L`(对手得分)、`E`(结束标志)组成。 - 所有字符需处理到 `E` 为止,`E` 之后的内容可忽略。 - 输入保证至少有一个有效比分。 **示例输入** ``` WWWWWWWWWWWE ``` --- ### **输出格式** 1. **第一部分**:按 11 分制输出所有局的比分,每局占一行,格式为 `华华得分:对手得分`。 2. **第二部分**:按 21 分制输出所有局的比分,格式同上。 3. 若未完成一局(即未满足获胜条件且未到 `E`),仍需输出当前比分。 **示例输出** ``` 11:0 21:0 ``` --- ### **解题思路** 1. **输入处理** - 读取所有字符直到遇到 `E`,过滤无效字符(如空格、换行)。 2. **模拟比赛过程** - 分别对 **11 分制** 和 **21 分制** 进行两次独立的模拟。 - 维护当前局的比分 `a`(华华得分)和 `b`(对手得分)。 3. **判断胜负条件** - 当一方得分 ≥11(或 21)且领先 ≥2 分时,记录该局比分并重置为 0:0。 - 若遇到 `E`,直接输出未完成的比分(即使未满足条件)。 --- ### **关键代码逻辑(伪代码)** ```python 读取所有字符,过滤后存入列表 s def simulate(rule): a, b = 0, 0 results = [] for ch in s: if ch == 'W': a += 1 elif ch == 'L': b += 1 # 检查是否满足结束条件 if (a >= rule or b >= rule) and abs(a - b) >= 2: results.append(f"{a}:{b}") a, b = 0, 0 # 处理未完成的局 if a != 0 or b != 0: results.append(f"{a}:{b}") return results 输出 11 分制的结果 输出空行 输出 21 分制的结果 ``` --- ### **注意事项** 1. **边界条件** - 比分可能为 10:12(11 分制无效,需继续比赛)或 20:22(21 分制有效)。 2. **输入处理** - 需正确处理多行输入,并过滤非 `W/L/E` 的字符。 3. **输出格式** - 每局比分单独一行,两部分结果间需有空行。 --- 通过模拟比赛过程并严格判断胜负条件,即可高效解决此题。建议自行构造测试数据(如平分、险胜等场景)验证代码逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值