NC16746 神奇盘子
题目
题目描述
有一个神奇的盘子,形状为圆形。盘子上面爬着一个大象(视作一个点)。由于现实的扭曲,当大象在盘子某个直径的一端的时候,可以瞬间传送至直径的另一端。现在大象想去盘子上另外一点,问他最少需要移动多少距离。传送不计距离。
输入描述
第一行一个整数r(1 <= r <= 1000)代表盘子的半径。
接下来两行两个整点分别代表大象所在的位置和大象目标的位置坐标。保证两个点都在圆内(可能在边界上),圆心在点(0, 0)上。
输出描述
输出一个实数,代表大象最短需要移动多少距离。和标程相对或绝对相差1e-6都算正确。
示例1
输入
1 0 1 0 -1
输出
0.000000000000
示例2
输入
4 3 0 -3 0
输出
2.000000000000
说明
示例3
输入
100 -59 76 3 69
输出
62.393909959226
题解
知识点:计算几何,三分。
可以知道圆周上有一极小点使得通过传送的方法后距离是最短的,用这个最小值,与直接走过去对比取最小。
对弧度三分 ,用参数方程表示出圆周上点坐标,随后计算两个三分点的各自距离之和,然后比较舍大区间。
要注意的是误差开大一点。
可以通过 取得较精确的值。
对称点的原弧度加上 生成即可。
实数范围 和 都可以,因为都在误差范围。
时间复杂度
空间复杂度
代码
#include <bits/stdc++.h> using namespace std; const double PI = acos(-1.0); const double eps = 1e-6; struct Point { double x, y; }a, b; double r; double dist(Point a, Point b) { return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); } Point f(double rad) { return { r * cos(rad), r * sin(rad) }; } bool check(double mid1, double mid2) { double d1 = dist(a, f(mid1)) + dist(f(mid1 + PI), b); double d2 = dist(a, f(mid2)) + dist(f(mid2 + PI), b); return d1 <= d2; } int main() { std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); cin >> r >> a.x >> a.y >> b.x >> b.y; double ans = dist(a, b); double l = 0, r = 2 * PI; while (r - l >= eps) { double mid1 = l + (r - l) / 3; double mid2 = r - (r - l) / 3; if (check(mid1, mid2)) r = mid2; else l = mid1; } ans = min(ans, dist(a, f(l)) + dist(f(l + PI), b)); cout << fixed << setprecision(8) << ans << '\n'; return 0; }
本文来自博客园,作者:空白菌,转载请注明原文链接:https://www.cnblogs.com/BlankYang/p/16421717.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧