UVA 12304 /// 圆的综合题 圆的模板
题目大意:
①给出三角形三个点,求三角形外接圆,求外接圆的圆心和半径。
②给出三角形三个点,求三角形内接圆,求内接圆的圆心和半径。
③给出一个圆,和一个点,求过该点的圆的切线与x轴的夹角(0<=angle<180);
④给出一条直线,一个点p,指定半径r,求经过点p的与直线相切的半径为r的圆;
⑤给出两条直线,求与这两条直线相切的圆;
⑥给出两个圆,求同时与这两个圆相切的圆;
贴一下圆的模板 带了一些注释
主要包括以下内容
// 求三角形abc的外接圆c(圆心、半径)
C csC(P a,P b,P c)
// 求三角形abc的内接圆c(圆心、半径)
C isC(P a,P b,P c)
// 直线l与圆c的交点 返回个数 交点坐标存入s
int insLC(L l,C c,vector<P>& s)
// 圆c1与c2的交点 返回个数 交点坐标存入s
int insCC(C c1,C c2,vector<P>& s)
// 过点p求与圆c相切的切线 返回条数 切线向量存入v
int PCgetL(P p,C c,vector <P>& v)
// 过点p求与直线l相切的半径为r的圆 返回个数 圆心坐标存入ans
int PLgetC(P p,L l,double r,vector <P>& ans)
// 求与直线l1和l2相切的半径为r的圆 返回个数 圆心坐标存入ans
int LLgetC(L l1,L l2,double r,vector<P>& ans)
// 求圆c1和c2的公切线 返回条数 切线与c1的交点存入ansa 与c2的交点存入ansb
int CCgetL(C c1,C c2,vector <P>& ansa,vector <P>& ansb)
// 求圆c1与c2的相交面积 (本题中无用 只是顺便贴一下)
double insAreaCC(P c1, double r1, P c2, double r2)
// 求n个点的最小圆覆盖(圆心、半径)
C MCC()
解法其实也多种多样 这里放两份题解
https://www.cnblogs.com/dilthey/p/7758012.html
https://blog.csdn.net/peteryuanpan/article/details/40315381
#include <bits/stdc++.h>
#define pb(a) push_back(a)
#define PI acos(-1)
using namespace std; const double eps=1e-;
double add(double a,double b) {
if(abs(a+b)<eps*(abs(a)+abs(b))) return ;
return a+b;
}
struct P {
double x,y;
P(){}
P(double _x,double _y):x(_x),y(_y){}
P operator - (P p) {
return P(add(x,-p.x),add(y,-p.y)); }
P operator + (P p) {
return P(add(x,p.x),add(y,p.y)); }
P operator * (double d) {
return P(x*d,y*d); }
P operator / (double d) {
return P(x/d,y/d); }
double dot (P p) {
return add(x*p.x,y*p.y); }
double det (P p) {
return add(x*p.y,-y*p.x); }
bool operator == (const P& p)const {
return abs(x-p.x)<eps && abs(y-p.y)<eps; }
bool operator < (const P& p)const {
return x<p.x || (x==p.x && y<p.y);
}
void read() {
scanf("%lf%lf",&x,&y); }
};
struct L {
P p, v;
double ang;
L(){}
L(P _p,P _v):p(_p),v(_v){ ang=atan2(v.y,v.x); }
P acP(double t) {
return p+v*t;
}
};
struct C {
P p; double r;
C(){}
C(P _p,double _r):p(_p),r(_r){}
P acP(double a) {
return P(p.x+cos(a)*r,p.y+sin(a)*r);
}
void read() {
scanf("%lf%lf%lf",&p.x,&p.y,&r); }
};
// 求向量a的长度
double lenP(P a) {
return sqrt(a.dot(a));
}
// 求向量v的垂直单位向量
P normal(P v) {
double len=lenP(v);
return P(-v.y/len,v.x/len);
}
// 求旋转ang后的向量v
P Rotate(P v,double ang) {
P u=P(sin(ang),cos(ang));
return P(v.det(u),v.dot(u));
}
// 求两向量夹角
double Angle(P u,P v) {
return acos(u.dot(v)/lenP(u)/lenP(v));
}
// 求向量v极角
double angle(P v) {
return atan2(v.y,v.x);
}
// 求点c到直线ab距离
double lenPL(P a,P b,P c) {
if(a==b) return lenP(a-c);
if((b-a).dot(c-a)<) return lenP(a-c);
else if((b-a).dot(c-b)>) return lenP(b-c);
else return abs((c-a).det(b-a))/lenP(a-b);
}
// 求两直线交点
P ins(L a,L b) {
P v=a.p-b.p, v1=a.v, v2= b.v;
double t=v2.det(v)/v1.det(v2);
return a.p+v1*t;
} /*求直线l与圆c的交点个数
t1 t2为交点对应的圆心角
交点存入s中
*/
int insLC(L l,C c,vector<P>& s) {
double ta=l.v.x, tb=l.p.x-c.p.x;
double tc=l.v.y, td=l.p.y-c.p.y;
double A=ta*ta+tc*tc, B=*(ta*tb+tc*td), C=tb*tb+td*td-c.r*c.r;
double delta=B*B-4.0*A*C; double t1,t2; // 圆心角
if(delta<-eps) return ; // <0无解
else if(abs(delta)<eps) { // =0存在一个解
t1=t2=-B/(2.0*A); s.pb(l.acP(t1));
return ;
}
else { // 两个解
t1=(-B-sqrt(delta))/(2.0*A); s.pb(l.acP(t1));
t2=(-B+sqrt(delta))/(2.0*A); s.pb(l.acP(t2));
return ;
}
} /* 判断两圆相交
求圆c1与c2的交点 并用s保存交点
*/
int insCC(C c1,C c2,vector<P>& s) {
double d=lenP(c1.p-c2.p);
if(abs(d)<eps) {
if(abs(c1.r-c2.r)<eps) return -; // 重合
return ; // 内含
}
if((c1.r+c2.r-d)<-eps) return ; // 外离
if(d-abs(c1.r-c2.r)<-eps) return ; // 内离 double ang=angle(c2.p-c1.p); // 向量c1c2求极角
double da=acos((c1.r*c1.r+d*d-c2.r*c2.r)/(*c1.r*d));
// c1与交点的向量 与 c1c2 的夹角
P p1=c1.acP(ang-da), p2=c1.acP(ang+da); // 求得两交点 s.pb(p1);
if(p1==p2) return ; // 同一个点
s.pb(p2); return ;
} /*求三角形的外接圆(圆心、半径)
*/
C csC(P a,P b,P c) {
double bx=b.x-a.x, by=b.y-a.y;
double cx=c.x-a.x, cy=c.y-a.y;
double d=*(cy*bx-cx*by);
double x=(cy*(bx*bx+by*by)-by*(cx*cx+cy*cy))/d+a.x;
double y=(bx*(cx*cx+cy*cy)-cx*(bx*bx+by*by))/d+a.y;
P r(x,y);
return C(r,lenP(a-r));
}
/*求三角形的内接圆(圆心、半径)
*/
C isC(P a,P b,P c) {
double d=lenP(b-c), e=lenP(c-a), f=lenP(a-b);
P p=(a*d+b*e+c*f)/(d+e+f);
return C(p,lenPL(a,b,p));
} /*过定点p作圆c的切线l
得p到圆心的向量(固定方向)求距离dist 判断距离
旋转向量(以p点为心旋转)得到切线向量 并存入v
*/
int PCgetL(P p,C c,vector <P>& v) {
P u=c.p-p; // p到圆心的向量
double dist=lenP(u);
if(dist-c.r<-eps) return ; // p在圆内
else if(abs(dist-c.r)<eps) { // p在圆上
v.pb(Rotate(u,PI/)); return ;
}
else {
double ang=asin(c.r/dist); // 切线与u的夹角
v.pb(Rotate(u,-ang));
v.pb(Rotate(u,ang));
return ;
}
} /*过点p与直线l相切的半径为r的圆
以点p为圆心r为半径得到圆pc
直线l向上和向下平移r后得到lup和ldw
得到圆pc与直线lup和ldw的交点 就是圆心 并存入ans
*/
int PLgetC(P p,L l,double r,vector <P>& ans) {
P v=normal(l.v); v=v/lenP(v)*r;
L lup(l.p+v,l.v), ldw(l.p-v,l.v);
int c1=insLC(lup,C(p,r),ans);
int c2=insLC(ldw,C(p,r),ans);
sort(ans.begin(),ans.end());
return c1+c2;
} /*与两条相交直线相切的半径为r的圆
直线向上和向下平移r后得到lup和ldw
每两条直线的交点即为圆心 并存入ans中
*/
int LLgetC(L l1,L l2,double r,vector<P>& ans) {
P v1=normal(l1.v), v2=normal(l2.v);
v1=v1/lenP(v1)*r, v2=v2/lenP(v2)*r;
L l1up(l1.p+v1,l1.v), l1dw(l1.p-v1,l1.v);
L l2up(l2.p+v2,l2.v), l2dw(l2.p-v2,l2.v); ans.pb(ins(l1up,l2up));
ans.pb(ins(l1up,l2dw));
ans.pb(ins(l1dw,l2up));
ans.pb(ins(l1dw,l2dw));
sort(ans.begin(),ans.end());
return ans.size();
} /*求圆c1与c2的公切线
重合无数条 内离则没有
内切有一条 相交有两条
外切有三条 外离有四条
返回切线的数量 切点存入
*/
int CCgetL(C c1,C c2,vector <P>& ansa,vector <P>& ansb) {
if(c1.r<c2.r) swap(c1,c2), swap(ansa,ansb);
P v=c2.p-c1.p;
double d2=(v).dot(v); // 圆心距的平方
double base=angle(v);
double rd=c1.r-c2.r; // 内切时的圆心距
double rs=c1.r+c2.r; // 外切时的圆心距 if(d2<rd*rd) return ; // 内离
if(d2== && c1.r==c2.r) return -; // 重合
if(d2==rd*rd) {
ansa.pb(c1.acP(base)), ansb.pb(c2.acP(base));
return ;
} // 内切 double ang=acos(rd/sqrt(d2)); // 外公切线与两圆心连线的夹角
ansa.pb(c1.acP(base+ang)); ansb.pb(c2.acP(base+ang));
ansa.pb(c1.acP(base-ang)); ansb.pb(c2.acP(base-ang));
// 两条外切线 if(d2==rs*rs) {
ansa.pb(c1.acP(base)); ansb.pb(c2.acP(base));
} // 外切
else if(d2>rs*rs) {
ang=acos(rs/sqrt(d2)); // 内公切线与两圆心连线的夹角
ansa.pb(c1.acP(base+ang)); ansb.pb(c2.acP(base+ang));
ansa.pb(c1.acP(base+ang)); ansb.pb(c2.acP(base+ang));
} // 外离 return ansa.size();
} /*求圆c1与c2的面积交
S扇形 = r*r*ang = r*l (l为弧长 l=ang*r)
S三角形 = r*r*sin(ang)*cos = r*r*0.5*sin(2*ang) = 0.5*r*h
S = S扇形 - S三角形 (对应圆弧的半边)
*/
double insAreaCC(P c1, double r1, P c2, double r2) {
double a = lenP(c1-c2), b = r1, c = r2;
double minr = min(r1,r2);
if(r1+r2-a<eps) return ; // 两圆相离
if(a-abs(r1-r2)<eps || abs(a)<eps)
return PI*minr*minr; // 两圆包含 double cosA=(a * a + b * b - c * c) / 2.0 / (a * b);
double cosB=(a * a + c * c - b * b) / 2.0 / (a * c);
double angA = acos(cosA), angB = acos(cosB); double s1 = r1*r1*angA - r1*r1*sin(angA)*cosA;
double s2 = r2*r2*angB - r2*r2*sin(angB)*cosB; return s1 + s2;
} /**********************************/ void ops3(P p,C c) {
vector <P> Lp; Lp.clear();
int m=PCgetL(p,c,Lp); /// 得到切线向量
vector <double> ans; ans.clear();
for(int i=;i<m;i++) {
double ang=angle(Lp[i]); /// 切线向量转为极角
if(ang<) ang+=PI;
if(abs(ang-PI)<eps) ang-=PI;
ans.pb(ang);
}
sort(ans.begin(),ans.end());
printf("[");
for(int i=;i<m;i++){
if(i!=) printf(",");
printf("%.6f",ans[i]*/PI); /// 极角转为角度
}
printf("]\n");
}
void ops4(P p,L l,double r) {
vector <P> ans; ans.clear();
int m=PLgetC(p,l,r,ans);
printf("[");
for(int i=;i<m;i++)
{
if(i!=) printf(",");
printf("(%.6lf,%.6lf)",ans[i].x,ans[i].y);
}
printf("]\n");
}
void ops5(L l1,L l2,double r) {
vector <P> ans; ans.clear();
int m=LLgetC(l1,l2,r,ans);
printf("[");
for(int i=;i<m;i++) {
if(i!=) printf(",");
printf("(%.6lf,%.6lf)",ans[i].x,ans[i].y);
}
printf("]\n");
}
void ops6(C c1,C c2,double r)
{
c1.r+=r, c2.r+=r;
vector <P> ans; ans.clear();
insCC(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 op;
while(cin>>op) {
if(op=="CircumscribedCircle") {
P p1,p2,p3;
p1.read(), p2.read(), p3.read();
C c=csC(p1,p2,p3);
printf("(%.6f,%.6f,%.6f)\n",c.p.x,c.p.y,c.r);
}
else if(op=="InscribedCircle") {
P p1,p2,p3;
p1.read(), p2.read(), p3.read();
C c=isC(p1,p2,p3);
printf("(%.6f,%.6f,%.6f)\n",c.p.x,c.p.y,c.r);
}
else if(op=="TangentLineThroughPoint") {
C c; c.read();
P p; p.read();
ops3(p,c);
}
else if(op=="CircleThroughAPointAndTangentToALineWithRadius") {
P p; P a,b;
p.read(), a.read(), b.read();
double r; scanf("%lf",&r);
ops4(p,L(a,b-a),r);
}
else if(op=="CircleTangentToTwoLinesWithRadius") {
P a,b; P c,d;
a.read(), b.read();
c.read(), d.read();
double r; scanf("%lf",&r);
ops5(L(a,b-a),L(c,c-d),r);
}
else { //if(op=="CircleTangentToTwoDisjointCirclesWithRadius") {
C c1, c2;
c1.read(), c2.read();
double r; scanf("%lf",&r);
ops6(c1,c2,r);
}
} return ;
}
随机增量法O(n)求最小圆覆盖
https://www.luogu.org/problemnew/solution/P1742
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3fLL
#define inc(i,j,k) for(int i=j;i<=k;i++)
#define dec(i,j,k) for(int i=j;i>=k;i--)
#define mem(i,j) memset(i,j,sizeof(i))
#define bug(args...) cout<<#args<<"="<<args<<endl;
const int N=1e5+;
const double eps=1e-; struct P {
double x,y;
P(){} P(double x,double y):x(x),y(y){}
P operator - (P p) { return P(x-p.x,y-p.y); }
P operator + (P p) { return P(x+p.x,y+p.y); }
P operator / (double d) { return P(x/d,y/d); }
P operator * (double d) { return P(x*d,y*d); }
double dot(P p) { return x*p.x+y*p.y; }
double det(P p) { return x*p.y-y*p.x; }
};
struct C {
P p; double r;
C(){} C(P p,double r):p(p),r(r){}
}; double len(P p) { return sqrt(p.dot(p)); }
double len2(P p) { return p.dot(p); }
/*求三角形的外接圆(圆心、半径)*/
C csC(P a,P b,P c) {
double bx=b.x-a.x, by=b.y-a.y;
double cx=c.x-a.x, cy=c.y-a.y;
double d=*(cy*bx-cx*by);
double x=(cy*(bx*bx+by*by)-by*(cx*cx+cy*cy))/d+a.x;
double y=(bx*(cx*cx+cy*cy)-cx*(bx*bx+by*by))/d+a.y;
P r(x,y);
return C(r,len(a-r));
}
/*求n个点的最小圆覆盖(圆心、半径)*/
C MCC() {
C c=C(P(0.0,0.0),0.0);
inc(i,,n) if(len2(p[i]-c.p)>c.r) {
c=C(p[i],0.0);
inc(j,,i-) if(len2(p[j]-c.p)>c.r) {
c.p=(p[i]+p[j])/,c.r=len2(p[j]-c.p);
inc(k,,j-) if(len2(p[k]-c.p)>c.r)
c=csC(p[i],p[j],p[k]), c.r=len2(p[k]-c.p);
}
}
c.r=sqrt(c.r);
return c;
} int n;
P p[N]; int main()
{
while(~scanf("%d",&n)) {
inc(i,,n) scanf("%lf%lf",&p[i].x,&p[i].y);
random_shuffle(p+,p++n);
C c=MCC();
printf("%.10f\n%.10f %.10f\n",c.r,c.p.x,c.p.y);
} return ;
}
UVA 12304 /// 圆的综合题 圆的模板的更多相关文章
- uva 12304点与直线与圆之间的关系
Problem E 2D Geometry 110 in 1! This is a collection of 110 (in binary) 2D geometry problems. Circum ...
- UVA 12304 - 2D Geometry 110 in 1! - [平面几何基础题大集合][计算几何模板]
题目链接:https://cn.vjudge.net/problem/UVA-12304 题意: 作为题目大合集,有以下一些要求: ①给出三角形三个点,求三角形外接圆,求外接圆的圆心和半径. ②给出三 ...
- UVa 12304 (6个二维几何问题合集) 2D Geometry 110 in 1!
这个题能1A纯属运气,要是WA掉,可真不知道该怎么去调了. 题意: 这是完全独立的6个子问题.代码中是根据字符串的长度来区分问题编号的. 给出三角形三点坐标,求外接圆圆心和半径. 给出三角形三点坐标, ...
- uva 12304
题意:要求解答6个关于圆的问题. 1.给出三角形坐标求外接圆 2.给出三角形坐标求内切圆 3.给出一个圆心和半径已知的圆,求过点(x,y)的所有和这个圆相切的直线 4.求所有和已知直线相切的过定点(x ...
- UVa 1339 Ancient Cipher --- 水题
UVa 1339 题目大意:给定两个长度相同且不超过100个字符的字符串,判断能否把其中一个字符串重排后,然后对26个字母一一做一个映射,使得两个字符串相同 解题思路:字母可以重排,那么次序便不重要, ...
- UVa 1225 Digit Counting --- 水题
UVa 1225 题目大意:把前n(n<=10000)个整数顺次写在一起,12345678910111213...,数一数0-9各出现多少字 解题思路:用一个cnt数组记录0-9这10个数字出现 ...
- UVa 1586 Molar mass --- 水题
UVa 1586 题目大意:给出一种物质的分子式(不带括号),求分子量.本题中分子式只包含4种原子,分别为C.H.O.N, 原子量分别为12.01,1.008,16.00,14.01 解题思路:先实现 ...
- UVa 272 Tex Quotes --- 水题
题目大意:在TeX中,左引号是 ``,右引号是 ''.输入一篇包含双引号的文章,你的任务是把他转成TeX的格式 解题思路:水题,定义一个变量标记是左引号还是右引号即可 /* UVa 272 Tex Q ...
- UVa 1583 Digit Generator --- 水题+打表
UVa 1583 题目大意:如果x加上x的各个数字之和得到y,那么称x是y的生成元. 给定数字n,求它的最小生成元 解题思路:可以利用打表的方法,提前计算出以i为生成元的数,设为d,并保存在a[d]中 ...
随机推荐
- php开发面试题---Mysql常用命令行大全
php开发面试题---Mysql常用命令行大全 一.总结 一句话总结: 常见关键词:create,use,drop,insert,update,select,where ,from.inner joi ...
- 框架-.NET:Spring.Net
ylbtech-框架-Spring.Net:Spring.Net Spring.NET为建立企业级应用提供了一套轻量级的解决方案.通过Spring.NET,我们可以用统一且透明的方式来配置应用程序.S ...
- setjmp与longjmp的分析
#include <setjmp.h> int main(int argc, const char* argv[]) { jmp_buf buf = {0,}; int k = 0; ...
- VirtualBox的源码学习
VMM重要的组件 TRPM (Trap Manager) PGM (Page Manager) REM (Recompiled Execution Manager) EM (Execution Man ...
- 【react】---Hooks的基本使用---【巷子】
一.react-hooks概念 React中一切皆为组件,React中组件分为类组件和函数组件,在React中如果需要记录一个组件的状态的时候,那么这个组件必须是类组件.那么能否让函数组件拥有类组件的 ...
- Linxu下JMeter进行接口压力测试
****************************************************************************** 本文主要介绍Jmeter脚本如何在Linx ...
- 自从阿里买了Flink母公司以后,你不懂Flink就out了!
个免费报名权限 Ps:小助理手动给大家发送资料,精力有限,仅限前100名免费领取,这份资料对于想要提升大数据技能进阶的小伙伴来说,将会是一份不可或缺的宝贵资料. 特别感谢飞总的部分原创支持!
- 兼容ie8浏览器的准备工作
一.html5shiv.js和respond.min.js html5shiv:解决ie9以下浏览器对html5新增标签的不识别,并导致CSS不起作用的问题. respond.min:让不支持css3 ...
- Linux 安装 python3.6
Linux下安装Python3.6和第三方库 如果本机安装了python2,尽量不要管他,使用python3运行python脚本就好,因为可能有程序依赖目前的python2环境, 比如yum!!! ...
- ubuntu安装WPS替代office
安装 1.下载地址:http://community.wps.cn/download/(去WPS官网下载) 下载第一个即可 2.执行安装命令: sudo dpkg -i wps-office_10.1 ...