poj 1375

来源:互联网 发布:日本留学去哪 知乎 编辑:程序博客网 时间:2024/06/13 14:22

题目: Click here


题意:给出一个光源,给出一些圆,求投影区间。 就是求切线。


0 0 主要是最近在做几何的模版。所以贴一下。。


#include <cstdio>#include <cstdlib>#include <iostream>#include <cmath>#include <algorithm>using namespace std;const double eps = 1e-8;const double inf = 1e12;const int N = 11111;struct point{double x,y;point(){x=0,y=0;}point(double _x,double _y){x=_x; y=_y;}}light;struct circle{point o;double r;}Cir[N];struct line{point p1,p2;line(){};line(point _p1,point _p2){p1 = _p1,p2 =_p2;}};bool equal(double x,double y){if(  y-x < eps && x - y < eps)return true;else return false;}struct node{double l, r;bool operator < (const node &tmp) const{if( (l<tmp.l) || (equal(l,tmp.l) && r<tmp.r)) return true;return false;};}tp[N];int n;//通过圆外一点,求出两个切点pOn1,pOn2void CalcQieDian(point pCenter, double r, point pOut,point &pOn1,point &pOn2) { point E,F,G; //1. 坐标平移到圆心ptCenter处,求园外点的新坐标EE.x= pOut.x-pCenter.x;E.y= pOut.y-pCenter.y; //平移变换到E  //2. 求园与OE的交点坐标F, 相当于E的缩放变换double t= r / sqrt (E.x * E.x + E.y * E.y);  //得到缩放比例 F.x= E.x * t;   F.y= E.y * t;   //缩放变换到F //3. 将E旋转变换角度a到切点G,其中cos(a)=r/OF=t, 所以a=arccos(t); double a1=acos(t),a2=-acos(t);   //得到旋转角度  //double a=-acos(t); 得到另一个点G.x=F.x*cos(a1) -F.y*sin(a1);G.y=F.x*sin(a1) +F.y*cos(a1);    //旋转变换到G //5. 返回H pOn1 = point(G.x+pCenter.x,G.y+pCenter.y);//在计算一次G.x=F.x*cos(a2) -F.y*sin(a2);G.y=F.x*sin(a2) +F.y*cos(a2);    //旋转变换到G pOn2 = point(G.x+pCenter.x,G.y+pCenter.y); //6. 实际应用过程中,只要一个中间变量E,其他F,G,H可以不用。}//通过圆外一点,求两条切线void CalcQieLine(circle &o,point &out,line &l1,line &l2){point pOn1,pOn2;CalcQieDian(o.o,o.r,out,pOn1,pOn2);if(pOn2.x < pOn1.x){swap(pOn2,pOn1);}l1=line(out,pOn1);l2=line(out,pOn2);}//当y已经知道的时候,通过直线的y推导出xdouble CalcPointUseLine(line &l,double y){return l.p2.x - (l.p2.y-y)*(l.p2.x-l.p1.x)/(l.p2.y-l.p1.y);}//返回投影的两个点void CalcTouYing(circle &o,point &out,node &ans){line l1,l2;CalcQieLine(o,out,l1,l2);ans.l = CalcPointUseLine(l1,0.0);ans.r = CalcPointUseLine(l2,0.0);}int main(){while(scanf("%d",&n) && n){cin >> light.x >> light.y;for(int i = 0;i < n;i++){cin >> Cir[i].o.x >> Cir[i].o.y >> Cir[i].r;}for(int i = 0;i < n;i++){CalcTouYing(Cir[i],light,tp[i]);}sort(tp,tp+n);double L=tp[0].l,R=tp[0].r;for(int i = 1;i < n;i++){if(R < tp[i].l){printf("%.2lf %.2lf\n",L,R);L = tp[i].l, R = tp[i].r;}else{R = max(R,tp[i].r);}}printf("%.2lf %.2lf\n\n",L,R);}return 0;}


0 0
原创粉丝点击