解题思路:
(1)传送面板:https://blog.dotcpp.com/a/63859
思路和这个差不多,这个人写的很详细,而且我 debug 时还参考了这个人的代码,直接看他的就完事了。
(2)本题的难度在于建模而不是算法,只要搞清楚数学公式就好写了,剩下的就是细心。
(3)核心思想:对移动的绝对距离来说,台球每移动 2L 相当于没动,这个 L 指的是台球桌的边长,需要在 x 轴和 y 轴分开考虑,即 2L 和 2W。
此外,台球有体积,要注意半径的影响。减去周期后最后剩 2 种情况:[0, L] 和 (L, 2L],分开考虑。
注意事项:
(1)角度转弧度别用 #define pi 3.1415 了,用 acos(-1) 表示 PI。
(2)减去周期后最后简化为 2 种情况:一次没反弹和反弹一次。
(3)构建新球桌时减去的 R 要在最后补上。
参考代码:
// 题目 1075: 台球碰撞 #include <iostream> #include <cmath> #include <iomanip> #define pi 3.1415 // 精度不够,会导致答案错误 using namespace std; int main() { int L, W; // 台球桌长宽 int x, y, R; // 初始球心位置和台球半径 int a, v, s; // 初始角度,速度,经过时间 double resX, resY; // 最终球心位置 while (cin >> L >> W >> x >> y >> R >> a >> v >> s) { if (!L) { break; // 球桌长度不可能为0,为0说明是结束输入的标志 } // 考虑球的碰撞体积后的实际台球桌,球心到达新的球桌边缘时球的边缘碰到旧的球桌边缘 L -= 2 * R; W -= 2 * R; x -= R; y -= R; double arc = a * acos(-1) / 180; // 正确的角度转弧度 // 球距离原点的总位移,必须取绝对值 double length = fabs(x + v * s * cos(arc)); double width = fabs(y + v * s * sin(arc)); // 每移动2L实际坐标没变 while (length > 2 * L ) { length -= 2 * L; } while (width > 2 * W) { width -= 2 * W; } // <= L 说明去除周期运动后,球实际上移动的距离尚未触发反弹 // > L && <= 2L 说明球实际上相当于只触发了一次反弹 // W 同理 if (length <= L) { resX = length + R; } else { resX = 2 * L - length + R; } if (width <= W) { resY = width + R; } else { resY = 2 * W - width + R; } cout << fixed << setprecision(2) << resX << " " << resY << endl; } // end while return 0; }
0.0分
10 人评分
程序员的表白 (C语言代码)浏览:1575 |
C语言程序设计教程(第三版)课后习题7.4 (Java代码)浏览:873 |
2003年秋浙江省计算机等级考试二级C 编程题(2) (C语言代码)浏览:729 |
妹子杀手的故事 (C语言代码)浏览:737 |
蓝桥杯历届试题-九宫重排 (C++代码)浏览:2812 |
字符串对比 (C语言代码)浏览:1471 |
字符串的输入输出处理 (C语言代码)浏览:1019 |
A+B for Input-Output Practice (IV) (C语言代码)浏览:484 |
C语言程序设计教程(第三版)课后习题1.5 (C语言代码)浏览:593 |
用筛法求之N内的素数。 (C语言代码)浏览:685 |