1 条题解

  • 0
    @ 2025-5-5 13:29:44

    题意分析

    题目背景

    本题属于保龄球计分系统模拟问题,要求根据输入的投球数据,按照保龄球规则计算并输出每局的得分和累计总分。关键在于正确识别全中(strike)、补中(spare)等特殊情况,并计算相应的额外得分。

    核心规则

    1. 基本得分:每击倒一个球瓶得1分。
    2. 全中(X):第一次投球击倒全部10个球瓶,得分=10 + 接下来两次投球的击倒数。
    3. 补中(/):两次投球击倒全部10个球瓶,得分=10 + 下一次投球的击倒数。
    4. 第十局特殊规则
      • 全中或补中后,可获得额外投球机会。
      • 额外投球的击倒数计入第十局总分。

    输入输出

    • 输入
      • 每行包含球手姓名和一系列数字,表示每次投球后剩余的球瓶数,以-1结束。
    • 输出
      • 第一行:姓名和每局投球标记(如X9/8-等)。
      • 第二行:累计得分,右对齐显示。

    解题思路

    1. 输入处理

    • 读取数据:逐行读取输入,解析球手姓名和投球数据。
    • 存储投球结果:用数组r[]存储每次投球后剩余的球瓶数。

    2. 投球标记生成

    • 遍历投球数据
      • 全中(X):剩余球瓶数为0时标记为X
      • 补中(/):两次投球击倒全部10个球瓶时标记为/
      • 普通情况:显示击倒的球瓶数,未击倒时用-表示。

    3. 得分计算

    • 初始化得分数组score[]存储每局得分。
    • 特殊得分处理
      • 全中:当前局得分=10 + 接下来两次投球的击倒数。
      • 补中:当前局得分=10 + 下一次投球的击倒数。
    • 累计总分:累加每局得分,右对齐输出。

    4. 输出格式化

    • 姓名左对齐:使用%-12s格式化。
    • 投球标记对齐:每局占3字符,左对齐。
    • 累计得分右对齐:使用%3d格式化。

    算法实现

    代码框架

    #include <stdio.h>
     
    int main(int argc, char *argv[]) 
    {
    	char name[25];	
    	int number, r[25], score[20];	
    	while(scanf("%s", name) > 0)
    	{
    		int k = 0, c = 0;
    		while(scanf("%d", &number) && number != -1)
    		{
    			r[k++] = number;
    		}
    		printf("%-12s", name);
    		for(int i = 0; i < k; ++i)
    		{
    			if(c++ < 10) printf(" ");
    			score[c] = 0;
    			
    			if(r[i] == 0) 
    			{
    				if(i + 1 < k && c < 10) printf("X  ");
    				else printf("X");
    				if(i + 2 < k)
    				{
    					if(r[i + 1] == 0)
    						score[c] = 10 + 10 + 10 - r[i + 2];
    					else score[c] = 10 + 10 - r[i + 2];
    				} 
    				else score[c] = -1;
    			}
    			else 
    			{
    				if(r[i] == 10) printf("-");
    				else printf("%d", 10 - r[i]);
    				if(i + 1 < k){
    					if(r[i + 1] == 0) {
    						printf("/");
    						if(i + 2 < k) score[c] = 10 + 10 - r[i + 2];
    						else score[c] = -1;
    					}
    					else if(r[i] == r[i + 1]) 
    					{
    						score[c] = 10 - r[i];
    						printf("-");
    					}
    					else {
    						score[c] = 10 - r[i + 1];
    						printf("%d", r[i] - r[i + 1]);
    					}
    				}
    				else score[c] = -1;
    				if(i + 2 < k && c < 10) printf(" ");
    				++i;
    			} 
    		}
    		printf("\n            ");
    		int total = 0;
    		for(int i = 1; i <= c; ++i) {
    			if(score[i] == -1) break;
    			total += score[i];
    			printf(" %3d", total);
    		}
    		printf("\n\n");
    	}
    	return 0;
    }
    

    关键步骤

    1. 输入解析:读取姓名和投球数据,存储剩余球瓶数。
    2. 标记生成
      • 全中:X
      • 补中:/
      • 普通情况:数字或-
    3. 得分计算
      • 全中:10 + next_two_balls
      • 补中:10 + next_ball
    4. 输出格式化:对齐姓名、投球标记和累计得分。

    复杂度分析

    • 时间O(n)O(n),其中nn为投球次数。
    • 空间O(n)O(n),存储投球数据和得分。
    • 1

    信息

    ID
    77
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    2
    已通过
    1
    上传者