UVA 12304 - 2D Geometry 110 in 1! - [平面几何基础题大集合][计算几何模板]
题目链接:https://cn.vjudge.net/problem/UVA-12304
题意:
作为题目大合集,有以下一些要求:
①给出三角形三个点,求三角形外接圆,求外接圆的圆心和半径。
②给出三角形三个点,求三角形内接圆,求内接圆的圆心和半径。
③给出一个圆,和一个点,求过该点的圆的切线与x轴的夹角(0<=angle<180);
④给出一条直线,一个点p,指定半径r,求经过点p的与直线相切的半径为r的圆;
⑤给出两条直线,求与这两条直线相切的圆;
⑥给出两个圆,求同时与这两个圆相切的圆;
题解:
综合运用平面几何模板即可。
AC代码:
#include<bits/stdc++.h>
using namespace std; //--------------------------------------计算几何模板 - st-------------------------------------- const double eps = 1e-; struct Point{
double x,y;
Point(double tx=,double ty=):x(tx),y(ty){}
};
typedef Point Vctor; //向量的加减乘除
Vctor operator + (Vctor A,Vctor B){return Vctor(A.x+B.x,A.y+B.y);}
Vctor operator - (Point A,Point B){return Vctor(A.x-B.x,A.y-B.y);}
Vctor operator * (Vctor A,double p){return Vctor(A.x*p,A.y*p);}
Vctor operator / (Vctor A,double p){return Vctor(A.x/p,A.y/p);}
bool operator < (Point A,Point B){return A.x < B.x || (A.x == B.x && A.y < B.y);} struct Line{
Point p;
Vctor v;
Line(Point p=Point(0,0),Vctor v=Vctor(,)):p(p),v(v){}
Point point(double t){return p + v*t;} //获得直线上的距离p点t个单位长度的点
};
struct Circle{
Point c;
double r;
Circle(Point tc=Point(,),double tr=):c(tc),r(tr){}
Point point(double a){return Point( c.x + cos(a)*r , c.y + sin(a)*r);}
}; int dcmp(double x)
{
if(fabs(x)<eps) return ;
else return (x<)?(-):();
}
bool operator == (Point A,Point B){return dcmp(A.x-B.x)== && dcmp(A.y-B.y)==;} //向量的点积,长度,夹角
double Dot(Vctor A,Vctor B){return A.x*B.x+A.y*B.y;}
double Length(Vctor A){return sqrt(Dot(A,A));}
double Angle(Vctor A,Vctor B){return acos(Dot(A,B)/Length(A)/Length(B));} //叉积,三角形面积
double Cross(Vctor A,Vctor B){return A.x*B.y-A.y*B.x;}
double TriangleArea(Point A,Point B,Point C){return Cross(B-A,C-A);} //向量的旋转,求向量的单位法线(即左转90度,然后长度归一)
Vctor Rotate(Vctor A,double rad){return Vctor( A.x*cos(rad) - A.y*sin(rad) , A.x*sin(rad) + A.y*cos(rad) );}
Vctor Normal(Vctor A)
{
double L = Length(A);
return Vctor(-A.y/L, A.x/L);
} //直线的交点
Point getLineIntersection(Line L1,Line L2)
{
Vctor u = L1.p-L2.p;
double t = Cross(L2.v,u)/Cross(L1.v,L2.v);
return L1.p + L1.v*t;
} //点到直线的距离
double DistanceToLine(Point P,Line L)
{
return fabs(Cross(P-L.p,L.v))/Length(L.v);
} //点到线段的距离
double DistanceToSegment(Point P,Point A,Point B)
{
if(A==B) return Length(P-A);
Vctor v1 = B-A, v2 = P-A, v3 = P-B;
if (dcmp(Dot(v1,v2)) < ) return Length(v2);
else if (dcmp(Dot(v1,v3)) > ) return Length(v3);
else return fabs(Cross(v1,v2))/Length(v1);
} //点到直线的映射
Point getLineProjection(Point P,Line L)
{
return L.v + L.v*Dot(L.v,P-L.p)/Dot(L.v,L.v);
} //判断线段是否规范相交
bool SegmentProperIntersection(Point a1,Point a2,Point b1,Point b2)
{
double c1 = Cross(a2 - a1,b1 - a1), c2 = Cross(a2 - a1,b2 - a1),
c3 = Cross(b2 - b1,a1 - b1), c4 = Cross(b2 - b1,a2 - b1);
return dcmp(c1)*dcmp(c2)< && dcmp(c3)*dcmp(c4)<;
} //判断点是否在一条线段上
bool OnSegment(Point P,Point a1,Point a2)
{
return dcmp(Cross(a1 - P,a2 - P))== && dcmp(Dot(a1 - P,a2 - P))<;
} //多边形面积
double PolgonArea(Point *p,int n)
{
double area=;
for(int i=;i<n-;i++) area += Cross( p[i]-p[] , p[i + ]-p[] );
return area/;
} //判断圆与直线是否相交以及求出交点
int getLineCircleIntersection(Line L,Circle C,vector<Point> &sol)
{
double t1,t2;
double a = L.v.x, b = L.p.x - C.c.x, c = L.v.y, d = L.p.y - C.c.y;
double e = a*a + c*c , f = *(a*b + c*d), g = b*b + d*d - C.r*C.r;
double delta = f*f - 4.0*e*g;
if(dcmp(delta)<) return ;
else if(dcmp(delta)==)
{
t1 = t2 = -f/(2.0*e);
sol.push_back(L.point(t1));
return ;
}
else
{
t1 = (-f-sqrt(delta))/(2.0*e); sol.push_back(L.point(t1));
t2 = (-f+sqrt(delta))/(2.0*e); sol.push_back(L.point(t2));
return ;
}
} //判断并求出两圆的交点
double angle(Vctor v){return atan2(v.y,v.x);}
int getCircleIntersection(Circle C1,Circle C2,vector<Point> &sol)
{
double d = Length(C1.c - C2.c);
//圆心重合
if(dcmp(d)==)
{
if(dcmp(C1.r-C2.r)==) return -; //两圆重合
else return ; //包含关系
} //圆心不重合
if(dcmp(C1.r+C2.r-d)<) return ; // 相离
if(dcmp(fabs(C1.r-C2.r)-d)>) return ; // 包含 double a = angle(C2.c - C1.c);
double da = acos((C1.r*C1.r + d*d - C2.r*C2.r) / (*C1.r*d));
Point p1 = C1.point(a - da), p2 = C1.point(a + da);
sol.push_back(p1);
if(p1==p2) return ;
sol.push_back(p2);
return ;
} //求点到圆的切线
int getTangents(Point p,Circle C,vector<Line> &sol)
{
Vctor u=C.c-p;
double dis=Length(u);
if(dis<C.r) return ;
else if(dcmp(dis-C.r) == )
{
sol.push_back(Line(p,Rotate(u,M_PI/)));
return ;
}
else
{
double ang=asin(C.r/dis);
sol.push_back(Line(p,Rotate(u,-ang)));
sol.push_back(Line(p,Rotate(u,ang)));
return ;
}
} //求两圆的切线
int getCircleTangents(Circle A,Circle B,Point *a,Point *b)
{
int cnt = ;
if(A.r<B.r){swap(A,B);swap(a,b);}
//圆心距的平方
double d2 = (A.c.x - B.c.x)*(A.c.x - B.c.x) + (A.c.y - B.c.y)*(A.c.y - B.c.y);
double rdiff = A.r - B.r;
double rsum = A.r + B.r;
double base = angle(B.c - A.c);
//重合有无限多条
if(d2 == && dcmp(A.r - B.r) == ) return -;
//内切
if(dcmp(d2-rdiff*rdiff) == )
{
a[cnt] = A.point(base);
b[cnt] = B.point(base);
cnt++;
return ;
}
//有外公切线
double ang = acos((A.r - B.r) / sqrt(d2));
a[cnt] = A.point(base + ang); b[cnt] = B.point(base + ang); cnt++;
a[cnt] = A.point(base - ang); b[cnt] = B.point(base - ang); cnt++; //一条内切线
if(dcmp(d2-rsum*rsum) == )
{
a[cnt] = A.point(base);
b[cnt] = B.point(M_PI + base);
cnt++;
}//两条内切线
else if(dcmp(d2-rsum*rsum) > )
{
double ang = acos((A.r + B.r) / sqrt(d2));
a[cnt] = A.point(base + ang); b[cnt] = B.point(base + ang); cnt++;
a[cnt] = A.point(base - ang); b[cnt] = B.point(base - ang); cnt++;
}
return cnt;
} //--------------------------------------计算几何模板 - ed-------------------------------------- Circle CircumscribedCircle(Point p1,Point p2,Point p3) //求外切圆,三点不能共线
{
double up,down,x,y,r;
double& x1=p1.x, x2=p2.x, x3=p3.x;
double& y1=p1.y, y2=p2.y, y3=p3.y; up = (pow(x1,)-pow(x2,) + pow(y1,)-pow(y2,))*(y1-y3) - (pow(x1,)-pow(x3,) + pow(y1,)-pow(y3,))*(y1-y2);
down = *(y1-y3)*(x1-x2) - *(y1-y2)*(x1-x3);
x = up/down; up = (pow(x1,)-pow(x2,) + pow(y1,)-pow(y2,))*(x1-x3) - (pow(x1,)-pow(x3,) + pow(y1,)-pow(y3,))*(x1-x2);
down = *(y1-y2)*(x1-x3) - *(y1-y3)*(x1-x2);
y = up/down; r = sqrt( pow(x1-x,)+pow(y1-y,) ); return Circle(Point(x,y),r);
} Circle InscribedCircle(Point p1,Point p2,Point p3) //求内切圆,三点不能共线
{
double a,b,c,x,y,r;
double& x1=p1.x, x2=p2.x, x3=p3.x;
double& y1=p1.y, y2=p2.y, y3=p3.y; a = sqrt( pow(x2-x3,) + pow(y2-y3,) );
b = sqrt( pow(x3-x1,) + pow(y3-y1,) );
c = sqrt( pow(x1-x2,) + pow(y1-y2,) ); x = ( a*x1 + b*x2 + c*x3 )/( a+b+c );
y = ( a*y1 + b*y2 + c*y3 )/( a+b+c ); double p = (a+b+c)/;
r = sqrt( (p-a)*(p-b)*(p-c)/p ); return Circle(Point(x,y),r);
} bool Line_cmp(Line a,Line b){return a.v<b.v;}
void TangentLineThroughPoint(Circle C,Point p)
{
vector<Line> Lines;
int cnt=getTangents(p,C,Lines);
vector<double> ans;
for(int i=;i<cnt;i++)
{
double ang=angle(Lines[i].v);
if(ang<) ang+=M_PI;
if(!dcmp(ang-M_PI)) ang-=M_PI;
ans.push_back(ang);
}
sort(ans.begin(),ans.end());
printf("[");
for(int i=;i<ans.size();i++)
{
if(i!=) printf(",");
printf("%lf",*ans[i]/M_PI);
}
printf("]\n");
} void CircleThroughAPointAndTangentToALineWithRadius(Point p,Point d1,Point d2,double r)
{
Vctor normal=Normal(d2-d1);
normal=normal/Length(normal)*r;
Line l1=Line(d1+normal,d2-d1), l2=Line(d1-normal,d2-d1);
vector<Point> ans;
getLineCircleIntersection(l1,Circle(p,r),ans);
getLineCircleIntersection(l2,Circle(p,r),ans);
sort(ans.begin(),ans.end());
printf("[");
for(int i=;i<ans.size();i++)
{
if(i!=) printf(",");
printf("(%.6lf,%.6lf)",ans[i].x,ans[i].y);
}
printf("]\n");
} void CircleTangentToTwoLinesWithRadius(Line L1,Line L2,double r)
{
Vctor normal1=Normal(L1.v), normal2=Normal(L2.v);
normal1=normal1/Length(normal1)*r;
normal2=normal2/Length(normal2)*r;
Line L1_a=Line(L1.p+normal1,L1.v);
Line L1_b=Line(L1.p-normal1,L1.v);
Line L2_a=Line(L2.p+normal2,L2.v);
Line L2_b=Line(L2.p-normal2,L2.v);
vector<Point> ans;
ans.push_back(getLineIntersection(L1_a,L2_a));
ans.push_back(getLineIntersection(L1_a,L2_b));
ans.push_back(getLineIntersection(L1_b,L2_a));
ans.push_back(getLineIntersection(L1_b,L2_b));
sort(ans.begin(),ans.end());
printf("[");
for(int i=;i<ans.size();i++)
{
if(i!=) printf(",");
printf("(%.6lf,%.6lf)",ans[i].x,ans[i].y);
}
printf("]\n");
} void CircleTangentToTwoDisjointCirclesWithRadius(Circle C1,Circle C2,double r)
{
C1.r+=r, C2.r+=r;
vector<Point> ans;
getCircleIntersection(C1,C2,ans);
sort(ans.begin(),ans.end());
printf("[");
for(int i=;i<ans.size();i++)
{
if(i!=) printf(",");
printf("(%.6lf,%.6lf)",ans[i].x,ans[i].y);
}
printf("]\n");
} int main()
{
string input;
while(cin>>input)
{
if(input=="CircumscribedCircle")
{
Point p1,p2,p3;
cin>>p1.x>>p1.y>>p2.x>>p2.y>>p3.x>>p3.y;
Circle ans=CircumscribedCircle(p1,p2,p3);
printf("(%.6lf,%.6lf,%.6lf)\n",ans.c.x,ans.c.y,ans.r);
}
else if(input=="InscribedCircle")
{
Point p1,p2,p3;
cin>>p1.x>>p1.y>>p2.x>>p2.y>>p3.x>>p3.y;
Circle ans=InscribedCircle(p1,p2,p3);
printf("(%.6lf,%.6lf,%.6lf)\n",ans.c.x,ans.c.y,ans.r);
}
else if(input=="TangentLineThroughPoint")
{
Circle C;
Point p;
cin>>C.c.x>>C.c.y>>C.r>>p.x>>p.y;
TangentLineThroughPoint(C,p);
}
else if(input=="CircleThroughAPointAndTangentToALineWithRadius")
{
Point d1,d2;
Point p;
double r;
cin>>p.x>>p.y>>d1.x>>d1.y>>d2.x>>d2.y>>r;
CircleThroughAPointAndTangentToALineWithRadius(p,d1,d2,r);
}
else if(input=="CircleTangentToTwoLinesWithRadius")
{
Point p1,p2,p3,p4;
double r;
cin>>p1.x>>p1.y>>p2.x>>p2.y>>p3.x>>p3.y>>p4.x>>p4.y>>r;
CircleTangentToTwoLinesWithRadius(Line(p1,(p2-p1)),Line(p3,(p4-p3)),r);
}
else //if(input=="CircleTangentToTwoDisjointCirclesWithRadius")
{
Circle C1,C2;
double r;
cin>>C1.c.x>>C1.c.y>>C1.r>>C2.c.x>>C2.c.y>>C2.r>>r;
CircleTangentToTwoDisjointCirclesWithRadius(C1,C2,r);
}
}
}
UVA 12304 - 2D Geometry 110 in 1! - [平面几何基础题大集合][计算几何模板]的更多相关文章
- Uva 12304 - 2D Geometry 110 in 1!
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&p ...
- UVA-12304 2D Geometry 110 in 1! (有关圆的基本操作)
UVA-12304 2D Geometry 110 in 1! 该问题包含以下几个子问题 CircumscribedCircle x1 y1 x2 y2 x3 y3 : 三角形外接圆 Inscribe ...
- UVA12304 2D Geometry 110 in 1! 计算几何
计算几何: 堆几何模版就能够了. . .. Description Problem E 2D Geometry 110 in 1! This is a collection of 110 (in bi ...
- UVa 12304 (6个二维几何问题合集) 2D Geometry 110 in 1!
这个题能1A纯属运气,要是WA掉,可真不知道该怎么去调了. 题意: 这是完全独立的6个子问题.代码中是根据字符串的长度来区分问题编号的. 给出三角形三点坐标,求外接圆圆心和半径. 给出三角形三点坐标, ...
- UVA12304-2D Geometry 110 in 1!
就是给了六个关于圆的算法.实现它们. 注意的是,不仅输出格式那个符号什么的要一样.坐标的顺序也要从小到大-- 基本上没考虑什么精度的问题,然后就过了. 大白鼠又骗人.也许我的方法比較好? 我的做法就是 ...
- uva 12304点与直线与圆之间的关系
Problem E 2D Geometry 110 in 1! This is a collection of 110 (in binary) 2D geometry problems. Circum ...
- uva 12304
题意:要求解答6个关于圆的问题. 1.给出三角形坐标求外接圆 2.给出三角形坐标求内切圆 3.给出一个圆心和半径已知的圆,求过点(x,y)的所有和这个圆相切的直线 4.求所有和已知直线相切的过定点(x ...
- UVA 12304 /// 圆的综合题 圆的模板
题目大意: ①给出三角形三个点,求三角形外接圆,求外接圆的圆心和半径. ②给出三角形三个点,求三角形内接圆,求内接圆的圆心和半径. ③给出一个圆,和一个点,求过该点的圆的切线与x轴的夹角(0<= ...
- UVA - 10014 - Simple calculations (经典的数学推导题!!)
UVA - 10014 Simple calculations Time Limit: 3000MS Memory Limit: Unknown 64bit IO Format: %lld & ...
随机推荐
- Visual Assist X 10.8.2042的Crack破解补丁. 2014.06.25 (General release.)
VA小组时隔一个月又公布了新的版本号,这个版本号新添加了5个特性,修复了7-8个bug.而且也是稳定的Release版.所以这是很推荐更新的一个版本号. 对于破解补丁还是老规矩,请到我的下载空间下载, ...
- 项目管理PMP输入输出ITTO联系记忆
综述九大领域 项目管理的输入输出非常难记,原因在于理解起来也经不去推敲,故整理一个联想记忆版本,通过联想把输入输出都串起来达到记忆的目的,既然是联想,里面的内容逻辑只是为了好记,并无正确与否,请大家原 ...
- Linux+Redis实战教程_day03_Redis-set【重点】_有序set(了解)
2.redis-set[重点] Java HashSet 无序,不重复. Redis操作中,涉及到两个大数据集合的并集,交集,差集运算. 赋值: l sadd key values[value1.v ...
- Java -- 异常的捕获及处理 -- Java的异常处理机制
7.1.4 Java的异常处理机制 在整个Java的异常处理中,实际上也是按照面向对象的方式进行处理,处理的步骤如下: ⑴ : 一旦产生异常,则首先会产生一个异常类的实例化对象. ⑵ : 在try语句 ...
- Go面向对象(三)
go语言中的大多数类型都是值予以,并且都可以包含对应的操作方法,在需要的时候你可以给任意类型增加新方法.二在实现某个接口时,无需从该接口集成,只需要实现该接口要求的所有方法即可.任何类型都可以被any ...
- ios开发之--调试方法
概述 基本操作 全局断点 条件断点 开启僵尸对象 LLDB命令 概述 在开发项目的工程中,肯定会遇到各种各样的bug,且大多数的bug都和自己有关:那么在和bug斗智斗勇的过程中,如果能快速准确的一击 ...
- Linux man 命令
man命令可以用来查看Linux命令的帮助信息 .配置文件的帮助信息等等,通过不同的代号可以查看不同的帮助信息: 代号 含义 1 查看Linux命令的帮助信息(默认) 2 查看内核提供的函数的帮助信息 ...
- 深入浅出MFC——MFC多线程程序设计(七)
1. 从操作系统层面看线程——三个观念:模块(MDB).进程(PDB).线程(TDB) 2. “执行事实”发生在线程身上,而不在进程身上.也就是说,CPU调度单位是线程而非进程.调度器据以排序的,是每 ...
- JSPatch实现原理详解<二>
本文转载至 http://blog.cnbang.net/tech/2855/ 距离上次写的<JSPatch实现原理详解>有一个月的时间,在这段时间里 JSPatch 在不断地完善和改进, ...
- 《C++ Primer Plus》第17章 输入、输出和文件 学习笔记
流是进出程序的字节流.缓冲区是内存中的临时存储区域,是程序与文件或其他I/O设备之间的桥梁.信息在缓冲区和文件之间传输时,将使用设备(如磁盘驱动器)处理效率最高的尺寸以大块数据的方式进行传输.信息在缓 ...