hdu 6097 Mindis (反演点)
来源:互联网 发布:淘宝 串货 编辑:程序博客网 时间:2024/06/05 02:25
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6097
题目大意:给你圆内两个点P、Q,求圆上一点D,使得 |QD|+|PD|最短
在此之前我们先了解一下反演点的知识,参照百度百科:
一般指二维反演中的点。
二维上反演以一个特定的反演圆为基础:圆心O为反演中心,圆半径为常数k,把点P反演为点P'就是使得OP×OP'=r^2.
如点P在圆外可这样作:过点P作圆的切线(两条),两个切点相连与OP连线交点就是点P'.
如点P在圆内就把这一过程反过来即可:连结OP,过点P作直线垂直于OP,直线与圆的交点处的切线的交点就是点P'.
如点P在圆上,反演后仍是它自身.按上述方法都可用尺规作图完成.
题目思路:
那么可以知道因为OP*OP'=r*r那么易证明对于圆上任意一点T,▲OP'T与▲OTP相似 (因为两对边比例相等且夹角相等都为∠POT)
知道这个结论之后,我们求的 min|QD|+|PD| 可以转化为求 min|Q'D|+|P'D| 然后再按边的比例即可得到解
如果直线P'Q'与圆没有交点,那么答案为PQ中垂线与圆的交点。
否则答案为|P'Q'|
#include<bits/stdc++.h>using namespace std;const double eps=1e-8;struct point{double x,y;};double distance1(point p1,point p2)//求两点的距离 {return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));}point intersection(point u1,point u2,point v1,point v2)//求两条直线交点 {point ret=u1;double t=((u1.x-v1.x)*(v1.y-v2.y)-(u1.y-v1.y)*(v1.x-v2.x))/((u1.x-u2.x)*(v1.y-v2.y)-(u1.y-u2.y)*(v1.x-v2.x));ret.x+=(u2.x-u1.x)*t;ret.y+=(u2.y-u1.y)*t;return ret;}void intersection_line_circle(point c,double r,point l1,point l2,point& p1,point& p2)//求直线与圆交点 {point p=c;double t;p.x+=l1.y-l2.y;p.y+=l2.x-l1.x;p=intersection(p,c,l1,l2);double temp=r*r-distance1(p,c)*distance1(p,c);t=sqrt(temp)/distance1(l1,l2);p1.x=p.x+(l2.x-l1.x)*t;p1.y=p.y+(l2.y-l1.y)*t;p2.x=p.x-(l2.x-l1.x)*t;p2.y=p.y-(l2.y-l1.y)*t;}double ptoline(point p,point l1,point l2) { point midp; midp.x=(l1.x+l2.x)/2.0;midp.y=(l1.y+l2.y)/2.0;return distance1(p,midp);}point invpoint(point p,double k)//求点p对于原点O的反演点 {//反演点为向量x伸长 k倍point invp;invp.x=p.x*k;invp.y=p.y*k;return invp;}double solve(){double r,ans;point O,P,Q,invP,invQ,PQmid;scanf("%lf",&r);scanf("%lf%lf%lf%lf",&P.x,&P.y,&Q.x,&Q.y);O.x=O.y=0;//原点O为圆心 PQmid.x=(P.x+Q.x)/2.0;PQmid.y=(P.y+Q.y)/2.0;double k=(r*r/distance1(P,O)/distance1(P,O));invP=invpoint(P,k);invQ=invpoint(Q,k);if(distance1(P,O)<eps) ans=2.0*r;else if(r<ptoline(O,invP,invQ)) //两个反演点的连线在圆外,则答案为垂直平分线与圆的交点{point p1,p2;intersection_line_circle(O,r,O,PQmid,p1,p2);//求直线与圆交点 ans=min(distance1(P,p1)+distance1(Q,p1),distance1(P,p2)+distance1(Q,p2));} else {//cout<<"反演点"<<endl;ans=distance1(invP,invQ);ans*=distance1(P,O)/r;}return ans;}int main(){int T;scanf("%d",&T);while(T--) printf("%.8lf\n",solve());}
阅读全文
0 0
- hdu 6097 Mindis (反演点)
- HDU 6097 Mindis【计算几何+反演点】
- HDU 6097 Mindis(反演)
- hdu 6097 Mindis(几何反演)
- HDU 6097 Mindis(圆的反演)
- hdu 6097 Mindis
- hdu 6097 Mindis (高中数学)
- Mindis HDU-6097
- HDU 6097 Mindis
- hdu 6097 Mindis(几何)
- HDU 6097 Mindis
- HDU 6097 Mindis
- HDU 6097 Mindis【几何】
- HDU 6097 Mindis
- HDU 6097 Mindis
- HDU 6097 Mindis
- HDU 6097 Mindis 几何
- HDU 2017 多校联合训练赛6 1002 6097 Mindis 反演变换 计算几何
- Qt进程间通信 之使用QSharedMemory
- 从 MVC 到前后端分离
- Java核心技术点之集合框架
- wait()和sleep()的区别
- CCF CSP 201512-3 画图(Java-90分)
- hdu 6097 Mindis (反演点)
- chatterbot源码comparisons的测试
- iOS Coredata的基本使用
- js BOM
- Linux上Mysql 快速进入及常用命令
- 大数据具体有哪些类型你知道吗
- poj 2761 Feed the dogs (Treap+离线处理)
- POI下载EXCEL模板-设置列的属性!!!
- 好的产品原型具备哪些特点?