题目链接: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! - [平面几何基础题大集合][计算几何模板]的更多相关文章

  1. Uva 12304 - 2D Geometry 110 in 1!

    http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&p ...

  2. UVA-12304 2D Geometry 110 in 1! (有关圆的基本操作)

    UVA-12304 2D Geometry 110 in 1! 该问题包含以下几个子问题 CircumscribedCircle x1 y1 x2 y2 x3 y3 : 三角形外接圆 Inscribe ...

  3. UVA12304 2D Geometry 110 in 1! 计算几何

    计算几何: 堆几何模版就能够了. . .. Description Problem E 2D Geometry 110 in 1! This is a collection of 110 (in bi ...

  4. UVa 12304 (6个二维几何问题合集) 2D Geometry 110 in 1!

    这个题能1A纯属运气,要是WA掉,可真不知道该怎么去调了. 题意: 这是完全独立的6个子问题.代码中是根据字符串的长度来区分问题编号的. 给出三角形三点坐标,求外接圆圆心和半径. 给出三角形三点坐标, ...

  5. UVA12304-2D Geometry 110 in 1!

    就是给了六个关于圆的算法.实现它们. 注意的是,不仅输出格式那个符号什么的要一样.坐标的顺序也要从小到大-- 基本上没考虑什么精度的问题,然后就过了. 大白鼠又骗人.也许我的方法比較好? 我的做法就是 ...

  6. uva 12304点与直线与圆之间的关系

    Problem E 2D Geometry 110 in 1! This is a collection of 110 (in binary) 2D geometry problems. Circum ...

  7. uva 12304

    题意:要求解答6个关于圆的问题. 1.给出三角形坐标求外接圆 2.给出三角形坐标求内切圆 3.给出一个圆心和半径已知的圆,求过点(x,y)的所有和这个圆相切的直线 4.求所有和已知直线相切的过定点(x ...

  8. UVA 12304 /// 圆的综合题 圆的模板

    题目大意: ①给出三角形三个点,求三角形外接圆,求外接圆的圆心和半径. ②给出三角形三个点,求三角形内接圆,求内接圆的圆心和半径. ③给出一个圆,和一个点,求过该点的圆的切线与x轴的夹角(0<= ...

  9. UVA - 10014 - Simple calculations (经典的数学推导题!!)

    UVA - 10014 Simple calculations Time Limit: 3000MS Memory Limit: Unknown 64bit IO Format: %lld & ...

随机推荐

  1. 8 -- 深入使用Spring -- 2...3 使用@Resource配置依赖

    8.2.3 使用@Resource配置依赖 @Resource 位于javax.annotation包下,是来自Java EE规范的一个Annotation,Spring直接借鉴了该Annotatio ...

  2. MySQL存储过程的创建及调用

    阅读目录:MySQL存储过程_创建-调用-参数 存储过程:SQL中的“脚本” 1.创建存储过程 2.调用存储过程 3.存储过程体 4.语句块标签 存储过程的参数 1.in:向过程里传参 2.out:过 ...

  3. Create maintenance backup plan in SQL Server 2008 R2 using the wizard

    You will need to identify how you want your maintenance plan to be setup. In this example the mainte ...

  4. ClamAV病毒软件的安装和使用

    ClamAV 杀毒是Linux平台最受欢迎的杀毒软件,ClamAV属于免费开源产品,支持多种平台,如:Linux/Unix.MAC OS X.Windows.OpenVMS.ClamAV是基于病毒扫描 ...

  5. ThinkPad L421 如何进入BIOS?(已解决)

    开机屏幕出现ThinkPad标志时,快速按下 F1键 即可进入BIOS

  6. spy-debugger 前端调试工具

    一站式页面调试.抓包工具.远程调试任何手机浏览器页面,任何手机移动端webview(如:微信,HybirdApp等).支持HTTP/HTTPS,无需USB连接设备.    Language: Engl ...

  7. CopyTo 方法详解

    如果你就想复制一个字符串到另一个字符串,可以使用string的静态方法Copy 例如: string a = "hello"; string b = "world&quo ...

  8. DRM in Android详解--转

    DRM,英文全称为Digital Rights Management,译为数字版权管理.它是目前业界使用非常广泛的一种数字内容版权保护技术.随着知识产权保护受重视的程度日益提高,快速攻城略地得Andr ...

  9. java(8) HashMap源码

    系统环境: JDK1.7 HashMap的基本结构:数组 + 链表.主数组不存储实际的数据,存储的是链表首地址. 成员变量 //默认数组的初始化大小为16 static final int DEFAU ...

  10. sencha touch 侧边栏扩展(只隐藏不销毁)

    基于Ext.ux.MenuButton改造而来,和它不同的是,不会每次都去销毁侧边栏,只是单纯的隐藏,属性配置方面没啥区别,每次点击按钮显示时,会触发showMenu事件/方法 代码如下: /** * ...