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 }