原题链接:台球碰撞
解题思路:
(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分
7 人评分
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程
发表评论 取消回复