hdu 4063 福州赛区网络赛 圆 ****

画几个图后,知道路径点集一定是起点终点加上圆与圆之间的交点,枚举每两个点之间是否能走,能走则连上线,然后求一遍最短路即可

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<cmath>
  5 #include<algorithm>
  6 using namespace std;
  7 #define sqr(x) ((x)*(x))
  8 const double eps= 1e-6;
  9 const int maxc=30;
 10 const int maxp=1000;
 11 const double inf=1e20;
 12 double dsgn(double x)//return double
 13 {
 14     if(fabs(x)<eps)return 0;
 15     return x;
 16 }
 17 int isgn(double x)//return int
 18 {
 19     if(fabs(x)<eps)return 0;
 20     if(x<0)return -1;
 21     return 1;
 22 }
 23 struct point
 24 {
 25     double x, y;
 26     point() {}
 27     point(double xx, double yy):x(xx), y(yy) {}
 28     double length() const
 29     {
 30         return sqrt(sqr(x)+sqr(y));
 31     }
 32     point set(const double &m) const
 33     {
 34         double len=length();
 35         return point(x*m/len, y*m/len);
 36     }
 37     double sqrdist(const point &a)const
 38     {
 39         return sqr(a.x-x)+sqr(a.y-y);
 40     }
 41     double dist(const point &a)const
 42     {
 43         return sqrt(sqrdist(a));
 44     }
 45 } p[maxp];
 46 struct line
 47 {
 48     double a, b, c;
 49     line() {}
 50     line(double ta=1,  double tb=-1,  double tc=0):a(ta), b(tb), c(tc) {}
 51 };
 52 struct circle
 53 {
 54     point o;
 55     double r;
 56 } c[maxc];
 57 int pn, cn;
 58 double edge[maxp][maxp];
 59 
 60 int cir_relation(circle c1, circle c2)//判断两圆关系
 61 {
 62     double d=c1.o.dist(c2.o);
 63     int a=isgn(d-c1.r-c2.r);
 64     int b=isgn(d-fabs(c1.r-c2.r));
 65     if(a==0)return -2;//外切
 66     if(b==0)return -1;//内切
 67     if(a>0)return 2;//相离
 68     if(b<0)return 1;//内含
 69     return 0;//相交
 70 }
 71 point line_intersect(point p1, point p2, point q1, point q2)
 72 {
 73     point ans=p1;
 74     double t=((p1.x-q1.x)*(q1.y-q2.y)-(p1.y-q1.y)*(q1.x-q2.x))/
 75              ((p1.x-p2.x)*(q1.y-q2.y)-(p1.y-p2.y)*(q1.x-q2.x));
 76     ans.x += (p2.x-p1.x)*t;
 77     ans.y += (p2.y-p1.y)*t;
 78     return ans;
 79 }
 80 void line_cross_circle(point p, point q, point o, double r, point &pp, point &qq)
 81 {
 82     point tmp=o;
 83     tmp.x += p.y-q.y;
 84     tmp.y += q.x-p.x;
 85     tmp=line_intersect(tmp, o, p, q);
 86     double t=sqrt(r*r - sqr(tmp.dist(o)))/(p.dist(q));
 87     pp.x=tmp.x + (q.x-p.x)*t;
 88     pp.y=tmp.y + (q.y-p.y)*t;
 89     qq.x=tmp.x - (q.x-p.x)*t;
 90     qq.y=tmp.y - (q.y-p.y)*t;
 91 }
 92 void circle_intersect(circle c1, circle c2, point &p1, point &p2)
 93 {
 94     point u, v;
 95     double t, d;
 96     d=c1.o.dist(c2.o);
 97     t= (1+ (sqr(c1.r) -sqr(c2.r))/sqr(d))/2;
 98     u.x= c1.o.x+ (c2.o.x-c1.o.x)*t;
 99     u.y= c1.o.y+ (c2.o.y-c1.o.y)*t;
100     v.x= u.x+c1.o.y-c2.o.y;
101     v.y= u.y-c1.o.x+c2.o.x;
102     line_cross_circle(u, v, c1.o, c1.r, p1, p2);
103 }
104 point circle_tangent(circle c1, circle c2)
105 {
106     point t;
107     if(isgn(c1.o.dist(c2.o)-c1.r-c2.r)==0)
108     {
109         t.x=(c1.r*c2.o.x + c2.r*c1.o.x)/(c1.r+c2.r);
110         t.y=(c1.r*c2.o.y + c2.r*c1.o.y)/(c1.r+c2.r);
111         return t;
112     }
113     t.x=(c1.r*c2.o.x-c2.r*c1.o.x)/(c1.r-c2.r);
114     t.y=(c1.r*c2.o.y-c2.r*c1.o.y)/(c1.r-c2.r);
115     return t;
116 }
117 void findallpoint()
118 {
119     int i, j, rel;
120     point p1, p2;
121     for(i=1; i<=cn; i++)
122         for(j=i+1; j<=cn; j++)
123         {
124             rel=cir_relation(c[i], c[j]);
125             if(rel==0)
126             {
127                 circle_intersect(c[i], c[j], p1, p2);
128                 p[pn++]=p1;
129                 p[pn++]=p2;
130             }
131             else if(rel<0)
132                 p[pn++]=circle_tangent(c[i], c[j]);
133         }
134 }
135 
136 point tmp[100];
137 point qq[3], base;
138 bool cmp(point a, point b)
139 {
140     return a.dist(base)<b.dist(base);
141 }
142 bool insideok(point a, point b)
143 {
144     for(int i=1; i<=cn; i++)
145     {
146         if(isgn(c[i].r-a.dist(c[i].o))<0)continue;
147         if(isgn(c[i].r-b.dist(c[i].o))<0)continue;
148         return true;
149     }
150     return false;
151 }
152 double multiply(point sp, point ep, point op)
153 {
154     return (sp.x-op.x)*(ep.y-op.y)-(sp.y-op.y)*(ep.x-op.x);
155 }
156 bool onsegment(point a, point u, point v)
157 {
158     return isgn(multiply(v, a, u))==0 && isgn((u.x-a.x)*(v.x-a.x))<=0 && isgn((u.y-a.y)*(v.y-a.y))<=0;
159 }
160 
161 bool edgeok(point a, point b)
162 {
163     int i, j;
164     int cnt=0, num;
165 
166     tmp[cnt++]=a;
167     point p1, p2;
168     for(i=1; i<=cn; i++)
169     {
170         line_cross_circle(a, b, c[i].o, c[i].r, p1, p2);
171         if(onsegment(p1, a, b))tmp[cnt++]=p1;
172         if(onsegment(p2, a, b))tmp[cnt++]=p2;
173     }
174     tmp[cnt++]=b;
175 
176     base=a;
177     sort(tmp, tmp+cnt, cmp);
178     for(i=1; i<cnt; i++)
179         if(!insideok(tmp[i-1], tmp[i]))
180             return false;
181     return true;
182 }
183 void findalledge()
184 {
185     int i, j;
186     for(i=0; i<pn; i++)
187         for(j=i+1; j<pn; j++)
188         {
189             if(edgeok(p[i], p[j]))
190                 edge[i][j]=edge[j][i]=p[i].dist(p[j]);
191             else
192                 edge[i][j]=edge[j][i]=-1;
193         }
194 }
195 bool has[maxp];
196 double dis[maxp];
197 void dijkstra()
198 {
199     int i, j, num;
200     double tmp;
201     for(i=0; i<pn; i++)has[i]=false, dis[i]=inf;
202     dis[0]=0;
203     for(i=0; i<pn; i++)
204     {
205         tmp=inf;
206         for(j=0; j<pn; j++)
207             if(!has[j] && dis[j]<tmp)
208             {
209                 tmp=dis[j];
210                 num=j;
211             }
212         has[num]=true;
213         for(j=0; j<pn; j++)
214             if(!has[j] && isgn(edge[num][j])>=0)
215                 dis[j]=min(dis[j], dis[num]+edge[num][j]);
216     }
217     if(dis[1]<inf)printf("%.4lf\n", dis[1]);
218     else printf("No such path.\n");
219 }
220 
221 void solve()
222 {
223     findallpoint();
224     findalledge();
225     dijkstra();
226 }
227 
228 int main()
229 {
230     int t, ca=1;
231     scanf("%d", &t);
232     while(t--0)
233     {
234         scanf("%d", &cn);
235         for(int i=1; i<=cn; i++)
236             scanf("%lf%lf%lf", &c[i].o.x, &c[i].o.y, &c[i].r);
237         pn=0;
238         p[pn++]=c[1].o;
239         p[pn++]=c[cn].o;
240         printf("Case %d: ", ca++);
241         solve();
242     }
243     return 0;
244 }

 

posted @ 2015-08-14 15:27  miao_a_miao  阅读(148)  评论(0编辑  收藏  举报