Problem B 1475 冰墩墩和冰壶

文章介绍了冰壶游戏的计分规则,并提供了一个C++程序来计算冰墩墩在游戏中的得分。程序通过输入冰壶的位置信息,计算各队离圆心的最短距离,然后判断胜负并输出得分。关键点包括指针的使用、输入处理和代码模块化。

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

目录

题目

冰墩墩和冰壶

题目描述

输入格式

输出格式

样例输入

样例输出

思路分析

区分 " Win " & " Lose "

计算分值

代码设计

需要实现的功能

需要的变量

代码模块化处理

需初始化数据

功能函数

输入函数

判断/计算/输出函数

主函数

提交代码

收获及总结

对于指针的使用

关于输入字符的小Tips

优化前想法及优化点及WA点


题目

冰墩墩和冰壶

Acceteped : 234

Submit : 769

Time Limit : 1000 MS

Memory Limit : 65536 KB

题目描述

冰壶是被誉为“冰面上的国际象棋”,其计分规则是各自投壶,最后在大本营内,你有几个壶离圆心比对方所有壶离圆心都近就得到几分。 比如红方有两个壶,分别在坐标(1,1),(−2,1);黄方也有两个壶,分别在(1,0),(0,2)。 由于黄方的第一个壶离圆心更近,而黄方的第二个壶没有红方第一个壶近,所以最后黄方得1分,红方不得分。

现在冰墩墩每次都选择红方,它想知道它到底得了多少分?


输入格式

第一行是一个整数T(1≤T≤3000),表示样例的个数。

每个样例的第一行是一个整数n(1≤n≤16),表示冰壶的数量。 以后每行一个冰壶的信息,为三个部分,第一个是一个字符,表示冰壶的颜色(R表示红色,Y表示黄色),后面是两个整数(数值的绝对值不超过1000),表示冰壶的坐标。

输入数据保证不会出现两个壶在同一个坐标。


输出格式

依次输出每个样例的结果。结果为一行,分为两个部分,如果没有让对方得分,输出“Win”和分数,否则输出”Lose”和对方得分的分数,两者之间相隔一个空格。


样例输入

2

4

Y 1 1

R -2 1

R 1 0

Y 0 2

4

Y 1 1

R 0 1

R 1 0

Y 0 2


样例输出

Win 1

Win 2

思路分析

区分 " Win " & " Lose "

对两个队伍的d ( 距离圆心最近的距离 ) 进行比较

计算分值

对于胜队 , 取其各冰壶距离与败队d进行比较

此处容易犯错的是 , 误以为两队冰壶数量相等 , 为冰壶总数的一半

代码设计

需要实现的功能

正确获取并储存输入数据

计算各队圆心距

得到各队最小圆心距

判断优胜队

计算优胜队最终得分

需要的变量

仅针对输入以及思路分析而言 , 其余间接应用变量在各模块中自行添加

样例数 T

冰壶总数 n

冰壶坐标 x , y

各队冰壶数目cnty , cntr

各队冰壶圆心距 Y[20] , R[20]

各队冰壶最小圆心距 miny , minr

优胜队分数score


代码模块化处理

需初始化数据

int T;
//int n;main()中可有可无,作为局部变量也可
//以下变量在样例循环内初始化
int Y[20] = {0};
int R[20] = {0};
int cnty = 0;
int cntr = 0;
int miny = 3000000;
int minr = 3000000;
//int score = 0;此处将判断函数与输出函数合并,故作为局部变量,直接计算并输出

功能函数

//功能函数(没有应用其他函数的那种)一般建议写在所有函数前
int Distance(int a, int b){
    return a * a + b * b;
}//计算圆心距,为方便比较不予开根号处理

输入函数

获取输入数据的同时获得最小圆心距
void Printin(int *Y, int *R, int *cnty, int *cntr, int *miny, int *minr){
    int n;//由于n仅在存储数据时有用,因此此处作为局部变量出现
    scanf("%d", &n);
    getchar();//吸收多余的回车
    while(n--){ 
        char team;
        int x, y;
        scanf("%c %d %d", &team, &x, &y);
        getchar();//吸收多余的回车
        if(team == 'Y'){
            *(Y + *cnty) = Distance(x, y);
            *miny = (*(Y + *cnty) < *miny) ? *(Y + *cnty) : *miny;//最小圆心距
            (*cnty)++;
        }
        else if(team == 'R'){
            *(R + *cntr) = Distance(x, y);
            *minr = (*(R + *cntr) < *minr) ? *(R + *cntr) : *minr;//最小圆心距
            (*cntr)++;
        }
    }
}

判断/计算/输出函数

在存储数据时可顺便记录数据数量及取最大or最小值
判断时也可以顺便输出了
void Judge(int *Y, int *R, int *cnty, int *cntr, int *miny, int *minr){
    int score = 0;
    if(*miny < *minr){//判断优胜队伍,若相等算胜利,即两者均不得分,按题意算R队获胜
        printf("Lose ");
        for(int i = 0;i < *cnty;i++){
            if(*(Y + i) < *minr) score++;//计算优胜队分数
        }
        printf("%d\n", score);
    }
    else{
        printf("Win ");
        for(int i = 0;i < *cntr;i++){
            if(*(R + i) < *miny) score++;//计算优胜队分数
        }
        printf("%d\n", score);
    }
}

主函数

int main(){
    int T;
    scanf("%d", &T);

    while(T--){
        int Y[20] = {0};
        int R[20] = {0};
        int cnty = 0;
        int cntr = 0;
        int miny = 3000000;
        int minr = 3000000;

        Printin(Y, R, &cnty, &cntr, &miny, &minr);
        Judge(Y, R, &cnty, &cntr, &miny, &minr);
    }

    return 0;
}

提交代码

Problem: 1475User: 202105501225
Memory: 1184KTime: 31MS
Language: G++Result: Accepted
#include <stdio.h>

int Distance(int a, int b){
    return a * a + b * b;
}

void Printin(int *Y, int *R, int *cnty, int *cntr, int *miny, int *minr){
    int n;
    scanf("%d", &n);
    getchar();
    while(n--){ 
        char team;
        int x, y;
        scanf("%c %d %d", &team, &x, &y);
        getchar();
        if(team == 'Y'){
            *(Y + *cnty) = Distance(x, y);
            *miny = (*(Y + *cnty) < *miny) ? *(Y + *cnty) : *miny;
            (*cnty)++;
        }
        else{
            *(R + *cntr) = Distance(x, y);
            *minr = (*(R + *cntr) < *minr) ? *(R + *cntr) : *minr;
            (*cntr)++;
        }
    }
}

void Judge(int *Y, int *R, int *cnty, int *cntr, int *miny, int *minr){
    int score = 0;
    if(*miny < *minr){
        printf("Lose ");
        for(int i = 0;i < *cnty;i++){
            if(*(Y + i) < *minr) score++;
        }
        printf("%d\n", score);
    }
    else{
        printf("Win ");
        for(int i = 0;i < *cntr;i++){
            if(*(R + i) < *miny) score++;
        }
        printf("%d\n", score);
    }
}

int main(){
    int T;
    scanf("%d", &T);

    while(T--){
        int Y[20] = {0};
        int R[20] = {0};
        int cnty = 0;
        int cntr = 0;
        int miny = 3000000;
        int minr = 3000000;

        Printin(Y, R, &cnty, &cntr, &miny, &minr);
        Judge(Y, R, &cnty, &cntr, &miny, &minr);
    }

    return 0;
}

收获及总结

对于指针的使用

更深刻的理解了指针与数组的关系

此处涉及的指向数组的指针 , 即是数组名 ( 指向数组首地址 )

所以此时在声明指针变量时 , 为int *Y ( 不是int *Y[]或其他 )

在使用函数时传输的变量也直接就是数组名

关于输入字符的小Tips

可以试试 , 把输入函数中的getchar()都删掉后

输入到字符变量team中的字符有什么变化

最直观的感受就是 , 数据还没输入完就输出结果了

原因在于此时%c读取了上一个scanf()的回车

解决办法有以下几种 :

  • 在%c的前一个scanf() ( 此函数中需要加的scanf()有两处 ) 后使用getchar()
  • 在%c的前一个scanf()末尾加上空格or ' \n 'or ' \t ' ( 两处 )
  • 在%c前面加上空格or ' \n 'or ' \t ' ( 在其他人题解上看见的 , 感觉是最方便的 )
还在消化scanf中空格的作用
找到了两篇感觉还可以的解释
可以结合起来看
【C语言】scanf语句吃掉回车或者空格问题详解_scanf吃掉回车符是什么意思_Z小旋的博客-CSDN博客
scanf函数%c前为什么加空格_对于scanf()而言,%c_hhhhhyyyyy8的博客-CSDN博客

优化前想法及优化点及WA点

< 对各队数组按距离远近重新排序依次比较 > 变为 < 选择最近距离用于比较 >

< 判断与输出分开 > 变为 < 判断与输出合并 >

WA是因为读题时理解错误 , 认为两队冰壶数一定相同


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Blue Irises.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值