hdu 6097 Mindis(多校联赛)
2017-08-11 20:39
459 查看
MindisTime Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Special Judge Problem Description The center coordinate of the circle C is O, the coordinate of O is (0,0) , and the radius is r. P and Q are two points not outside the circle, and PO = QO. You need to find a point D on the circle, which makes PD+QD minimum. Output minimum distance sum. Input The first line of the input gives the number of test cases T; T test cases follow. Each case begins with one line with r : the radius of the circle C. Next two line each line contains two integers x , y denotes the coordinate of P and Q. Limits T≤500000 −100≤x,y≤100 1≤r≤100 Output For each case output one line denotes the answer. The answer will be checked correct if its absolute or relative error doesn't exceed 10−6. Formally, let your answer be a, and the jury's answer be b. Your answer is considered correct if |a−b|max(1,b)≤10−6. Sample Input 4 4 4 0 0 4 4 0 3 3 0 4 0 2 2 0 4 0 1 1 0 Sample Output 5.6568543 5.6568543 5.8945030 6.7359174 Source 2017 Multi-University Training Contest - Team 6 |
圆心 O 坐标(0, 0), 给定两点 P, Q(不在圆外),满足 PO = QO,
要在圆上找一点 D,使得 PD + QD 取到最小值。
这道题其实更接近一道数学题 知识要用代码去实现它 比赛做这道题的时候没有足够的精力取好好思考了 关键是没能想到做出辅助的反演点来解决 感觉反演点这个地方确实是巧妙 让我想到了以前的一道经典的数学题 :一条河的同一侧有两个村庄 现在要在河上建立一个供水站 向两个村庄供水 求在哪建供水站 向两个村庄的铺设的水管最短 当然答案大家都知道 就是把期中一个村庄以河为对称轴做对称点 然后把这个对称点与另一个村庄连接 连线与河流的交线就是正确的选址地点
这里用到了反演的知识 其实反演点与对称点的作用类似
过点P做P的反演点P1,使得OP∗OP1=OD2=r2
则OPOD=ODOP1=DPDP1
然后后面的计算与d点的求值 都会用到相关的比例
当 P'Q' 与圆有交点时:
不妨设交点为 O',若 D 不为 O',则 P'D + Q'D > P'Q'(三角形两边之和大于第三边);当且仅当 D 取 O' 时,P'Q + Q'D 取到最小值,即为 P'Q'。
当 P'Q' 与圆无交点时:
不妨将 P' 与 Q' 看成椭圆的两个焦点,当椭圆慢慢变大时,第一个碰到的圆上的点 D 即为使得 P'D + Q'D 最小的点;画个图就很显然了,第一个碰到的点即为 PQ 的中垂线与圆的交点。
至于判断有 P'Q' 与圆有没有交点,就是圆心到直线的距离与半径比较,又因为此处 P'O=Q'O,所以只需要比较 P'Q' 的中点到圆心的距离和半径的大小。
代码会给出更详细的解释:
ac代码:
#include <bits/stdc++.h> #define eps 1e-8 //确定一个最小值 用于后续的比较 int main() { int T; scanf("%d", &T); while (T--) { double r, x1, y1, x2, y2; scanf("%lf%lf%lf%lf%lf", &r, &x1, &y1, &x2, &y2);//输入半径和点的坐标等信息 double d0 = sqrt(pow(x1, 2) + pow(y1, 2)); if (fabs(d0) < eps)//p和q两个点无限接近于原点 { printf("%.7f\n", 2 * r);//此时的pd+qd就相当与两条半径 continue; } double k = r * r / (d0 * d0);//用这个比值 确定p和q的反演点 double x3 = x1 * k, x4 = x2 * k, y3 = y1 * k, y4 = y2 * k;//x3 y3 x4 y4分别是p和q对应的反演点 double mx = (x3+x4)/2, my = (y3+y4)/2, ans;//mx和my是 p和q反演点连线的中点坐标(以下用连线中点代替) double d = sqrt(pow(mx,2)+pow(my,2));//原点(圆心)到pq反演点的中点的距离 if (d <= r)//判断反演点和半径的关系 如果两个反演点的中点到圆心的距离小于半径 {//即反演点之间的连线与圆相交或者相切 此时dp+qd的最小时的d点即是线与圆的交点 double dist = sqrt(pow(x3 - x4, 2) + pow(y3 - y4, 2));//长度符合反演点与原来点的比例关系 ans = dist * d0 / r; } else//其他的即是连线与圆相离时的状态 这时候的d点是p和q的反演点的连线的中垂线与圆的交点 { double kk = r / d;//找出半径和连线中点到圆心距离的比例 即是现在的d点坐标与连线中点坐标的比例 double smx = mx * kk, smy = my * kk;//求出连线中点的坐标 ans = 2 *sqrt(pow(smx - x1, 2) + pow(smy - y1, 2));//求出最后连线的长度 乘2是因为此时pd=qd } printf("%.7f\n", ans);//注意保留小数的位数 } return 0; }
相关文章推荐
- 2017 多校训练第六场 HDU 6097 Mindis
- 多校6 HDU-6097 Mindis 几何数学
- hdu 6097 Mindis(圆上一点到圆内(距圆心相等的)两点的距离和最短)
- 2016多校联赛 HDU 5858 Hard problem
- HDU6170 Two strings(dp,2017 HDU多校联赛 第9场)
- HDU 2017 多校联赛 1002 Balala Power!
- HDU 6097Mindis(利用椭圆二分)
- hdu 6097 Mindis(圆上一点到圆内(距圆心相等的)两点的距离和最短)
- HDU 4861(2014多校联赛1)1001 Couple doubi
- HDU 6097 Mindis
- hdu 4334 Trouble(2012多校联赛4,第3题)
- [2015hdu多校联赛补题]hdu5348 MZL's endless loop
- HDU 5358 · First One【尺取法】【读题】【多校联赛】
- HDU6165 FFF at Valentine(深搜dfs,2017 HDU多校联赛 第9场)
- HDU 4335What is N?2012多校联赛第四场(欧拉函数+坑数据)
- [2015hdu多校联赛补题]hdu5378 Leader in Tree Land
- HDU 2017 多校联赛-1001 Add More Zero
- hdu 6097 Mindis
- 2017 Multi-University Training Contest - Team 6-HDU 6097:Mindis
- 2017多校第6场 HDU 6097 Mindis 计算几何,圆的反演