2018 Wannafly summer camp Day2--New Game!

New Game!

描述

题目描述:

Eagle Jump公司正在开发一款新的游戏。泷本一二三作为其员工,获得了提前试玩的机会。现在她正在试图通过一个迷宫。

这个迷宫有一些特点。为了方便描述,我们对这个迷宫建立平面直角坐标系。迷宫中有两条平行直线 L1:Ax+By+C1=0L2:Ax+By+C2=0

还有 n个圆 Ci:(xxi)^2+(yyi)^2=ri^2。角色在直线上、圆上、圆内行走不消耗体力。在其他位置上由S点走到T点消耗的体力为ST的欧几里得距离。

泷本一二三想从 L1 出发,走到L2 。请计算最少需要多少体力。

输入:

第一行五个正整数 n,A,B,C1,C2 (1n1000,10000A,B,C1,C210000),其中 A,B不同时为 0。

接下来 n 行每行三个整数 x,y,r(10000x,y10000,1r10000) 表示一个圆心为 (x,y),半径为 r 的圆。

输出:

仅一行一个实数表示答案。与标准答案的绝对误差或者相对误差不超过10^4 即算正确。

样例输入
2 0 1 0 -4
0 1 1
1 3 1
样例输出
0.236068


由于圆是没有消耗的,所以可以将每个圆都坍缩成点,然后求L1到L2的最短路即可。
 1 #include<math.h>
 2 #include<stdio.h>
 3 #define MAXN 1000
 4 struct point 
 5 {
 6     double x,y;
 7 };
 8 struct line
 9 {
10     point a,b;
11 };
12 
13 double distance(point p1,point p2)
14 {
15     return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
16 }
17 double disptoline(point p1,double a,double b,double c)
18 {
19     double x=sqrt(a*a+b*b);
20     return fabs((a*p1.x+b*p1.y+c)/x);
21 }
22 
23 point pp[1005];
24 double r[1005];
25 double e[1005][1005],d[1005];
26 int used[1005];
27 double inf=1e9;
28 void dij(int s,int n)
29 {    int v,u,max=0;
30     
31     for(u=0;u<=n;u++)
32     d[u]=inf,used[u]=0;
33     
34     d[s]=0;
35 
36 
37     while(1)
38     {    v=-1;
39         for(u=0;u<=n;u++)
40         {    if(!used[u]&&(v==-1||d[u]<d[v]))
41             v=u;
42             
43         }
44         if(v==-1) break;
45         used[v]=1;
46         
47         for(u=0;u<=n;u++)
48         if(d[u]>d[v]+e[v][u])
49         d[u]=d[v]+e[v][u];
50     }
51 }
52 
53 int main()
54 {
55        int n;
56     double a,b,c1,c2;
57        scanf("%d",&n);
58        scanf("%lf%lf%lf%lf",&a,&b,&c1,&c2);
59        for(int i=0;i<=n+1;i++)
60        {
61      for(int j=0;j<=n+1;j++)
62      e[i][j]=inf;      
63     }
64        for(int i=1;i<=n;i++)
65        {
66            scanf("%lf%lf%lf",&pp[i].x,&pp[i].y,&r[i]);
67     }
68     
69     for(int i=1;i<=n;i++)
70     {
71         double lt=disptoline(pp[i],a,b,c1);
72     
73         if(lt<r[i]) e[0][i]=0;
74         else e[0][i]=lt-r[i];
75     }
76     for(int i=1;i<=n;i++)
77     {
78         double lt=disptoline(pp[i],a,b,c2);
79         if(lt<r[i]) e[i][n+1]=0;
80         else e[i][n+1]=lt-r[i];
81     }
82     for(int i=1;i<=n;i++)
83     for(int j=1;j<=n;j++)
84     {    if(i==j) continue;
85         double lt=distance(pp[i],pp[j]);
86         if(lt>r[i]+r[j]) e[i][j]=lt-r[i]-r[j];
87         else e[i][j]=0;
88     }
89     point t;
90     t.y=1.0,t.x=-(b*1.0+c1)/a;
91     e[0][n+1]=disptoline(t,a,b,c2);
92     dij(0,n+1);
93     
94     printf("%.10f
",d[n+1]);
95     return 0;
96 }
View Code
 
 

 

原文地址:https://www.cnblogs.com/FlyerBird/p/9459778.html