一、问题描述
本题涉及一个射击靶的得分计算,靶的中心在坐标系的原点 (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的得分。
二、分析与解题思路
-
数学建模:
-
点到圆心的距离可以用欧几里得距离公式计算: 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。
-
-
优化计算:
-
直接比较 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。
-
-
分支判断:
- 使用一系列条件判断语句(如 if-else 或 switch-case),对 x2+y2x^2 + y^2x2+y2 的值范围进行分段处理。
-
边界条件:
- 特殊边界值,如点恰好落在圆环边界(例如 x2+y2=4x^2 + y^2 = 4x2+y2=4),要正确归入对应分数。
三、常见错误分析
-
原代码中的错误:
-
使用浮点数运算(如
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逻辑不严谨,可能导致超出范围的点也返回有效分数。
- 问题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); // 超出所有环 } } -
优化点:
- 使用整数运算代替浮点运算,避免误差;
- 逐环判断逻辑清晰,代码可读性高;
- 通过直接比较平方值 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,…)时分数正确。
六、总结
本题考察了几何问题的建模能力和代码实现中的逻辑准确性。关键优化点在于:
- 用整数平方运算代替浮点数计算,避免误差;
- 分环逐步判断得分逻辑清晰,易于扩展和维护。
通过对问题的清晰建模、对错误代码的改进以及合理的优化,本题解法具备良好的鲁棒性和效率。# | 豆包MarsCode AI 刷题