UVA12304直线,圆,点的综合应用
来源:互联网 发布:网络理财平台排行榜 编辑:程序博客网 时间:2024/06/07 06:30
虽然这道题是个简单题,但对于我这样的弱渣还是研究了好久,而且自己根据大白书写的代码始终不对,无奈最后还是抄袭大神代码,
通过这个题得到下面几条心得,
1.做计算几何一定要注意精度问题,很难有绝对的相等,主要相对精度而言
2.做计算几何比较繁琐,一定要理清思路,代码思路一定要清晰
由于感觉大神的代码思路清晰,而且代码风格比较好,特贴出大神代码
,以及我自己按照大白书写的始终WA的代码,留着没事思考人生:
大神代码:
#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<cstring>#include<algorithm>#include<vector>#include<map>#include<set>#include<string>using namespace std;const double eps=1e-6;const double pi=acos(-1.0);int dcmp(double x){ if(fabs(x)<eps) return 0; return x>eps?1:-1;}struct point{ double x,y; point(){} point(double x,double y):x(x),y(y){} point operator + (const point &t) const { return point(x+t.x,y+t.y); } point operator - (const point &t) const { return point(x-t.x,y-t.y); } point operator * (const double &t) const { return point(x*t,y*t); } point operator / (const double &t) const { return point(x/t,y/t); } bool operator < (const point &t) const { return x+eps<t.x||(!dcmp(x-t.x)&&y<t.y); } double len() { return sqrt(x*x+y*y); } double len2() { return x*x+y*y; } point normal() { return point(-y,x)/len(); } void in() { cin>>x>>y; } void out() { printf("(%.6f,%.6f)",x,y); }};double dis(point a,point b){ return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}point rotate(point a,double ct){ return point(a.x*cos(ct)-a.y*sin(ct),a.y*cos(ct)+a.x*sin(ct));}double cross(point a,point b){ return a.x*b.y-a.y*b.x;}double dot(point a,point b){ return a.x*b.x+a.y*b.y;}double fix(double x){ if(x<-eps) x+=pi; return x*180./pi;}double angle(point v){ return atan2(v.y,v.x);}double disPointToLine(point a,point l,point r){ return fabs(cross(a-l,r-l))/dis(l,r);}struct Line{ point a,v; void in() { a.in(); v.in(); v=v-a; } Line(){} Line(point a,point v):a(a),v(v){}};void lineLineIntersect(Line l,Line r,vector<point> &sol){ double t=cross((r.a-l.a),r.v)/cross(l.v,r.v); sol.push_back(l.a+l.v*t);}struct Circle{ point o; double r; void in() { o.in(); cin>>r; } point getpoint(double ct) { return point(r*cos(ct),r*sin(ct))+o; } void out() { printf("(%.6f,%.6f,%.6f)\n",o.x,o.y,r); } Circle(point o,double r):o(o),r(r){} Circle(){}};void cirLineIntersect(Circle C,Line L,vector <point> &sol){ double e=L.v.len2(),f=dot(L.a-C.o,L.v)*2,g=(L.a-C.o).len2()-C.r*C.r; double dlt=f*f-4*e*g; if(dlt<-eps) return; if(dlt<eps) { double t=-f/(2*e); sol.push_back(L.v*t+L.a); return ; } dlt=sqrt(dlt); double t1=(-f+dlt)/(2*e),t2=(-f-dlt)/(2*e); sol.push_back(L.v*t1+L.a); sol.push_back(L.v*t2+L.a);}void cirCirIntersect(Circle C1,Circle C2, vector <point> &sol){ point v=C2.o-C1.o; double d=v.len(); if(dcmp(d-C1.r-C2.r)>0) return; double ct=angle(v),alf=acos((C1.r*C1.r+d*d-C2.r*C2.r)/(2*C1.r*d)); sol.push_back(C1.getpoint(ct+alf)); if(dcmp(alf)>eps) sol.push_back(C1.getpoint(ct-alf));}Circle CircumscribedCircle(point p1,point p2,point p3){ double bx = p2.x-p1.x, by = p2.y-p1.y;double cx = p3.x-p1.x, cy = p3.y-p1.y;double d = 2*(bx*cy-by*cx);double ox = (cy*(bx*bx+by*by) - by*(cx*cx+cy*cy))/d + p1.x;double oy = (bx*(cx*cx+cy*cy) - cx*(bx*bx+by*by))/d + p1.y;point o = point(ox, oy);return Circle(o,dis(o,p1));}Circle InscribedCircle(point p1, point p2, point p3){double a = dis(p2, p3);double b = dis(p1, p3);double c = dis(p1, p2);point o = (p1*a+p2*b+p3*c)/(a+b+c);return Circle(o, disPointToLine(o, p1, p2));}vector<double> TangentLineThroughPoint(point p,Circle c){ vector<double> sol; point u=c.o-p; double d=u.len(); if(d+eps<c.r) return sol; else if(!dcmp(d-c.r)) { sol.push_back(fix(angle(rotate(u,-pi/2)))); } else { double alf=asin(c.r/d); sol.push_back(fix(angle(rotate(u,-alf)))); sol.push_back(fix(angle(rotate(u,alf)))); } sort(sol.begin(),sol.end()); return sol;}vector <point> CircleThroughAPointAndTangentToALineWithRadius(point o, Line L, double r) {vector <point> sol;point v = L.v.normal();cirLineIntersect(Circle(o, r), Line(L.a+v*r, L.v), sol);cirLineIntersect(Circle(o, r), Line(L.a-v*r, L.v), sol);sort(sol.begin(), sol.end());return sol;}vector <point> CircleTangentToTwoLinesWithRadius(Line L1, Line L2, double r) {vector <point> sol;point v1 = L1.v.normal();point v2 = L2.v.normal();lineLineIntersect(Line(L1.a+v1*r, L1.v), Line(L2.a+v2*r, L2.v), sol);lineLineIntersect(Line(L1.a+v1*r, L1.v), Line(L2.a-v2*r, L2.v), sol);lineLineIntersect(Line(L1.a-v1*r, L1.v), Line(L2.a+v2*r, L2.v), sol);lineLineIntersect(Line(L1.a-v1*r, L1.v), Line(L2.a-v2*r, L2.v), sol);sort(sol.begin(), sol.end());return sol;}vector <point> CircleTangentToTwoDisjointCirclesWithRadius(Circle C1, Circle C2, double r) {vector <point> sol;cirCirIntersect(Circle(C1.o, C1.r+r), Circle(C2.o, C2.r+r), sol);sort(sol.begin(), sol.end());return sol;}string op;void print(vector <point> sol) {printf("[");for(int i = 0; i < sol.size(); i++) {sol[i].out();if(i != sol.size()-1) printf(",");}printf("]\n");}int main() {while(cin >> op) {if(op == "CircumscribedCircle") {point a, b, c;a.in(), b.in(), c.in();CircumscribedCircle(a, b, c).out();}else if(op == "InscribedCircle") {point a, b, c;a.in(), b.in(), c.in();InscribedCircle(a, b, c).out();}else if(op == "TangentLineThroughPoint") {Circle c; point p;c.in(); p.in();vector <double> ans = TangentLineThroughPoint(p, c);printf("[");for(int i = 0; i < ans.size(); i++) {printf("%.6f", ans[i]);if(i != ans.size()-1) printf(",");}printf("]\n");}else if(op == "CircleThroughAPointAndTangentToALineWithRadius") {point p; Line l; double r;p.in(), l.in(), scanf("%lf", &r);print(CircleThroughAPointAndTangentToALineWithRadius(p, l, r));}else if(op == "CircleTangentToTwoLinesWithRadius") {Line L1, L2; double r;L1.in(); L2.in(); scanf("%lf", &r);print(CircleTangentToTwoLinesWithRadius(L1, L2, r));}else if(op == "CircleTangentToTwoDisjointCirclesWithRadius") {Circle c1, c2; double r;c1.in(); c2.in(); scanf("%lf", &r);print(CircleTangentToTwoDisjointCirclesWithRadius(c1, c2, r));}}return 0;}自己的WA代码:
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cstdlib>#include<cmath>#include<cctype>#include<string>#include<map>#include<vector>#include<set>using namespace std;const double eps=1e-6;const double PI=acos(-1.0);int dcmp(double x){ if(fabs(x)<eps) return 0; return x>eps?1:-1;}struct Point{ double x,y; Point(){} Point(double x,double y):x(x),y(y){}};typedef Point Vector;Vector operator +(Vector A,Vector B){ return Vector(A.x+B.x,A.y+B.y);}Vector operator -(Vector A,Vector B){ return Vector(A.x-B.x,A.y-B.y);}Vector operator *(Vector A,double p){ return Vector(A.x*p,A.y*p);}Vector operator /(Vector A,double p){ return Vector(A.x/p,A.y/p);}bool operator <(const Point &a,const Point &b){ return a.x+eps<b.x||(!dcmp(a.x-b.x)&&a.y<b.y);}//bool operator ==(const Point &a,const Point &b)//{ // return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;//}double Dot(Vector A,Vector B){ return A.x*B.x+A.y*B.y;}double Length(Vector A){ return sqrt(Dot(A,A));}double Angle(Vector A,Vector B){ return acos(Dot(A,B)/Length(A)/Length(B));}double Cross(Vector A,Vector B){ return A.x*B.y-A.y*B.x;}Vector Rotate(Vector A,double rad){ return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));}Vector Normal(Vector A){ double L=Length(A); return Vector(-A.y/L,A.x/L);}double DistaceToLine(Point P,Point A,Point B){ Vector v1=B-A,v2=P-A; return fabs(Cross(v1,v2)/Length(v1));}double angle(Vector v){ return atan2(v.y,v.x);}double fix(double x){ if(x<-eps) x+=PI; return x*180.0/PI;}struct Line{ Point p; Vector v; Line() {} Line(Point p,Vector v):p(p),v(v){}; Point point(double t) { return Point(v*t+p); }};Point GetLineIntersection(Point P,Vector v,Point Q,Vector w){ Vector u=P-Q; double t=Cross(w,u)/Cross(v,w); return Vector(P+v*t);}struct Circle{ Point c; double r; Circle(Point c,double r):c(c),r(r){} Circle() {} Point point(double a) { return Point(c.x+cos(a)*r,c.y+sin(a)*r); }};void 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=2*(a*b+c*d),g=b*b+d*d-C.r*C.r; double delta=f*f-4*e*g; if(delta<-eps) return; if(delta<eps) { t1=t2=-f/(2*e); sol.push_back(L.point(t1)); return; } t1=(-f-sqrt(delta))/(2*e); sol.push_back(L.point(t1)); t2=(-f+sqrt(delta))/(2*e); sol.push_back(L.point(t2));}void getCircleIntersection(Circle C1,Circle C2,vector<Point> &sol){ double d=Length(C1.c-C2.c); if(dcmp(d-C1.r-C2.r)>0) return; double a=angle(C2.c-C1.c); double da=acos((C1.r*C1.r+d*d-C2.r*C2.r)/(2*C1.r*d)); sol.push_back(C1.point(a+da)); if(dcmp(da)>eps) sol.push_back(C1.point(a-da));}void work1(){ Point A,B,C; cin>>A.x>>A.y>>B.x>>B.y>>C.x>>C.y; Vector p1=A-B; Vector t1=Normal(p1); Point mid1=(A+B)/2; Vector p2=C-B; Vector t2=Normal(p2); Point mid2=(B+C)/2; Point T=GetLineIntersection(mid1,t1,mid2,t2); double r=Length(A-T); printf("(%.6f,%.6f,%.6f)\n",T.x,T.y,r); /* Point p1,p2,p3; cin>>p1.x>>p1.y>>p2.x>>p2.y>>p3.x>>p3.y; double Bx=p2.x-p1.x,By=p2.y-p1.y; double Cx=p3.x-p1.x,Cy=p3.y-p1.y; double D=2*(Bx*Cy-By*Cx); double cx=(Cy*(Bx*Bx+By*By)-By*(Cx*Cx+Cy*Cy))/D+p1.x; double cy=(Bx*(Cx*Cx+Cy*Cy)-Cx*(Bx*Bx+By*By))/D+p1.y; Point p=Point(cx,cy); printf("(%.6f,%.6f,%.6f)\n",p.x,p.y,Length(p1-p)); */}void work2(){ Point A,B,C; cin>>A.x>>A.y>>B.x>>B.y>>C.x>>C.y; Vector p1=A-B; Vector p2=C-B; Vector p3=C-A; double radb=Angle(p1,p2); double radc=Angle(p2,p3); cout<<radb<<radc<<endl; Vector BD=Rotate(p2,radb/2); Vector CD=Rotate(p3,radc/2); Point T=GetLineIntersection(B,BD,C,CD); double r=DistaceToLine(T,A,B); printf("(%.6f,%.6f,%.6f)\n",T.x,T.y,r); /* Point p1,p2,p3; cin>>p1.x>>p1.y>>p2.x>>p2.y>>p3.x>>p3.y; double a=Length(p2-p3); double b=Length(p3-p1); double c=Length(p1-p2); Point p=(p1*a+p2*b+p3*c)/(a+b+c); double r=DistaceToLine(p,p1,p2); printf("(%.6f,%.6f,%.6f)\n",p.x,p.y,r);*/}void work3(){ Circle C; Point p; cin>>C.c.x>>C.c.y>>C.r>>p.x>>p.y; // Circle C(c,r); Vector u=C.c-p; // cout<<u.x<<endl<<u.y<<endl; double dist=Length(u); // cout<<dist<<endl; if(dist+eps<C.r) printf("[]\n"); else if(dcmp(dist-C.r)==0) { Vector v=Rotate(u,-PI/2); // cout<<v.x<<endl<<v.y<<endl; // double radd=rad+PI/2; // if(radd==PI) radd-=PI; printf("[%.6f]\n",fix(angle(v))); } else { double ang=asin(C.r/dist); Vector v1=Rotate(u,-ang); Vector v2=Rotate(u,ang); double rad1=angle(v1); double rad2=angle(v2); if(rad1<rad2) swap(rad1,rad2); printf("[%.6f,%.6f]\n",fix(rad1),fix(rad2)); }}void work4(){ Point p,p1,p2; double r; cin>>p.x>>p.y>>p1.x>>p1.y>>p2.x>>p2.y; cin>>r; Line L(p1,p2-p1); Circle C(p,r); vector <Point> sol; Vector cc=Normal(L.v); getLineCircleIntersection(Line(L.p+cc*r,L.v),C,sol); getLineCircleIntersection(Line(L.p-cc*r,L.v),C,sol); sort(sol.begin(),sol.end()); // cout<<sol.size()<<endl; cout<<"["; for(int i=0;i<sol.size();i++) { printf("(%.6f,%.6f)",sol[i].x,sol[i].y); if(i!=sol.size()-1) cout<<","; } cout<<"]"<<endl;}void work5(){ 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; Line L1(p1,p2-p1),L2(p3,p4-p3); Vector LN1=Normal(L1.v); Vector LN2=Normal(L2.v); vector <Point> sol; sol.push_back(GetLineIntersection(L1.p+LN1*r,L1.v,L2.p+LN2*r,L2.v)); sol.push_back(GetLineIntersection(L1.p+LN1*r,L1.v,L2.p-LN2*r,L2.v)); sol.push_back(GetLineIntersection(L1.p-LN1*r,L1.v,L2.p+LN2*r,L2.v)); sol.push_back(GetLineIntersection(L1.p-LN1*r,L1.v,L2.p-LN2*r,L2.v)); sort(sol.begin(),sol.end()); cout<<"["; for(int i=0;i<sol.size();i++) { printf("(%.6f,%.6f)",sol[i].x,sol[i].y); if(i!=sol.size()-1) cout<<","; } cout<<"]"<<endl;}void work6(){ Circle C1,C2; double r; cin>>C1.c.x>>C1.c.y>>C1.r>>C2.c.x>>C2.c.y>>C2.r>>r; vector<Point> sol; getCircleIntersection(Circle(C1.c,C1.r+r),Circle(C2.c,C2.r+r),sol); sort(sol.begin(),sol.end()); cout<<"["; for(int i=0;i<sol.size();i++) { printf("(%.6f,%.6f)",sol[i].x,sol[i].y); if(i!=sol.size()-1) cout<<","; } cout<<"]"<<endl;}int main(){ string s; while(cin>>s) { if(s=="CircumscribedCircle") work1(); else if(s=="InscribedCircle") work2(); else if(s=="TangentLineThroughPoint") work3(); else if(s=="CircleThroughAPointAndTangentToALineWithRadius") work4(); else if(s=="CircleTangentToTwoLinesWithRadius") work5(); else if(s=="CircleTangentToTwoDisjointCirclesWithRadius") work6(); } return 0;}
0 0
- UVA12304直线,圆,点的综合应用
- UVa12304
- 遍历圆和直线上的点
- 直线上的点
- 点到直线的距离
- 点到直线的距离
- 点到直线的距离
- 点到直线的距离
- 点到直线的距离
- 穿点最多的直线
- 点到直线的距离
- hdu2857 直线交点 点关于某直线的对称点
- tzc3056 点关于直线的对称点
- 点关于直线的对称点
- 点到线段直线的距离, 直线与直线的关系 直线与线段的关系
- 圆与直线的大综合,计算几何(二维几何110合一!,uva 12304)
- MSHFlexGrid的综合应用
- listview的综合应用
- HTML5新特性之智能表单: required="required"指示输入字段的值是必需的
- Object-C内存管理
- typedef的用法总结
- LeetCode #3 Longest Substring Without Repeating Characters
- UVA - 11995 I Can Guess the Data Structure! STL模板
- UVA12304直线,圆,点的综合应用
- 学习和使用多种编程语言的感想
- 函数参数的传递问题(一级指针和二级指针)
- 对比
- hibernate缓存机制详细分析
- 建立一个Stack类,有min功能
- Android学习
- 31、签名解释 & eclipse实现签名过程
- Server Tomcat v7.0 Server at localhost was unable to start within 45 seconds