计算射击得分问题| 豆包MarsCode AI 刷题

177 阅读4分钟

一、问题描述

本题涉及一个射击靶的得分计算,靶的中心在坐标系的原点 (0,0)(0, 0)(0,0),靶上有十个同心圆环,半径依次为 1,2,…,101, 2, \dots, 101,2,…,10。每个圆环的得分规则如下:

  • 靶心内(半径为1)得分为10分;
  • 半径为2的圆环(不含靶心)得分为9分;
  • 半径为3的圆环(不含前两个环)得分为8分;
  • 依次递减,直到半径为10的圆环得分为1分;
  • 如果射击点在靶外(距离原点的距离大于10),得分为0分。

给定射击点的坐标 (x,y)(x, y)(x,y),需要计算小E的得分。

二、分析与解题思路

  1. 数学建模

    • 点到圆心的距离可以用欧几里得距离公式计算: r=x2+y2r = \sqrt{x^2 + y^2}r=x2+y2​

    • 射击点落在哪个圆环,取决于 rrr 的值:

      • 若 r≤1r \leq 1r≤1,得分为10;
      • 若 1<r≤21 < r \leq 21<r≤2,得分为9;
      • …\dots…;
      • 若 r>10r > 10r>10,得分为0。
  2. 优化计算

    • 直接比较 r=x2+y2r = \sqrt{x^2 + y^2}r=x2+y2​ 的值会涉及浮点数运算,这可能导致误差。

    • 因此,用距离平方 r2=x2+y2r^2 = x^2 + y^2r2=x2+y2 代替距离 rrr 进行判断。

      • 若 x2+y2≤12x^2 + y^2 \leq 1^2x2+y2≤12,得分为10;
      • 若 12<x2+y2≤221^2 < x^2 + y^2 \leq 2^212<x2+y2≤22,得分为9;
      • …\dots…;
      • 若 x2+y2>102x^2 + y^2 > 10^2x2+y2>102,得分为0。
  3. 分支判断

    • 使用一系列条件判断语句(如 if-else 或 switch-case),对 x2+y2x^2 + y^2x2+y2 的值范围进行分段处理。
  4. 边界条件

    • 特殊边界值,如点恰好落在圆环边界(例如 x2+y2=4x^2 + y^2 = 4x2+y2=4),要正确归入对应分数。

三、常见错误分析

  1. 原代码中的错误

    • 使用浮点数运算(如 Math.sqrt)计算距离 rrr,再将其转为整数进行比较:

      java
      复制代码
      double ans = Math.sqrt(x * x + y * y);
      if (ans <= 1) { return 10; }
      else if (ans <= 11) { return 11 - (int)ans; }
      else { return 0; }
      
      • 问题1:Math.sqrt 计算的结果是浮点数,直接截断为整数可能导致得分不准确。例如,射击点在 r=4.999r = 4.999r=4.999 时,会被误判为 r=4r = 4r=4。
      • 问题2:11 - (int)ans 逻辑不严谨,可能导致超出范围的点也返回有效分数。
  2. 逻辑不清晰

    • 没有针对圆环的分数规则逐环判断,直接通过数学公式处理,逻辑不够直观,容易出错。

四、优化后的解决方案

  1. 代码实现: 以下是优化后的代码,使用整数运算避免浮点误差,逻辑清晰且边界条件处理准确:

    java
    复制代码
    public class Main {
        public static int solution(int x, int y) {
            int distanceSquared = x * x + y * y; // 计算距离平方
    
            // 判断得分
            if (distanceSquared <= 1 * 1) {
                return 10;
            } else if (distanceSquared <= 2 * 2) {
                return 9;
            } else if (distanceSquared <= 3 * 3) {
                return 8;
            } else if (distanceSquared <= 4 * 4) {
                return 7;
            } else if (distanceSquared <= 5 * 5) {
                return 6;
            } else if (distanceSquared <= 6 * 6) {
                return 5;
            } else if (distanceSquared <= 7 * 7) {
                return 4;
            } else if (distanceSquared <= 8 * 8) {
                return 3;
            } else if (distanceSquared <= 9 * 9) {
                return 2;
            } else if (distanceSquared <= 10 * 10) {
                return 1;
            } else {
                return 0; // 超出所有环
            }
        }
    
        public static void main(String[] args) {
            System.out.println(solution(1, 0) == 10); // 靶心内
            System.out.println(solution(1, 1) == 9); // 第二环
            System.out.println(solution(0, 5) == 6); // 第五环
            System.out.println(solution(3, 4) == 6); // 第五环
            System.out.println(solution(7, 7) == 0); // 超出所有环
        }
    }
    
  2. 优化点

    • 使用整数运算代替浮点运算,避免误差;
    • 逐环判断逻辑清晰,代码可读性高;
    • 通过直接比较平方值 x2+y2x^2 + y^2x2+y2 提高性能,避免了开平方运算的开销。

五、测试与验证

  • 测试样例

    • 样例1:输入 x=1,y=0x = 1, y = 0x=1,y=0,输出为10;
    • 样例2:输入 x=1,y=1x = 1, y = 1x=1,y=1,输出为9;
    • 样例3:输入 x=0,y=5x = 0, y = 5x=0,y=5,输出为6;
    • 样例4:输入 x=3,y=4x = 3, y = 4x=3,y=4,输出为6;
    • 样例5:输入 x=7,y=7x = 7, y = 7x=7,y=7,输出为0。
  • 边界验证

    • 确保点落在圆环边界(如 x2+y2=1,4,9,…x^2 + y^2 = 1, 4, 9, \dotsx2+y2=1,4,9,…)时分数正确。

六、总结

本题考察了几何问题的建模能力和代码实现中的逻辑准确性。关键优化点在于:

  1. 用整数平方运算代替浮点数计算,避免误差;
  2. 分环逐步判断得分逻辑清晰,易于扩展和维护。

通过对问题的清晰建模、对错误代码的改进以及合理的优化,本题解法具备良好的鲁棒性和效率。# | 豆包MarsCode AI 刷题