链接:https://www.nowcoder.com/acm/contest/201/L
来源:牛客网
题目描述
Eagle Jump公司正在开发一款新的游戏。Hifumi Takimoto作为其中的员工,获得了提前试玩的机会。现在她正在试图通过一个迷宫。
这个迷宫有一些特点。为了方便描述,我们对这个迷宫建立平面直角坐标系。迷宫中有两条平行直线 L1:Ax+By+C1=0, L2:Ax+By+C2=0,还有 n 个圆 。角色在直线上、圆上、园内行走不消耗体力。在其他位置上由S点走到T点消耗的体力为S和T的欧几里得距离。
Hifumi Takimoto想从 L1 出发,走到 L2 。请计算最少需要多少体力。
输入描述:
第一行五个正整数 n,A,B,C1,C2 (1≤ n ≤ 1000, -10000 ≤ A,B,C1,C2 ≤ 10000),其中 A,B 不同时为 0。
接下来 n 行每行三个整数 x,y,r(-10000 ≤ x,y ≤ 10000, 1≤ r ≤ 10000) 表示一个圆心为 (x,y),半径为 r 的圆。
输出描述:
仅一行一个实数表示答案。与正确结果的绝对误差或者相对误差不超过 10-4 即算正确。
示例1
输入
复制
2 0 1 0 -4
0 1 1
1 3 1
输出
复制
0.236068
就把直线和圆都看成结点,然后计算他们之间的距离,然后Dijk求一下最短路
代码:
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
int n,a,b,c1,c2;
const int N=1005;
int x[N],y[N],r[N];
double dis1[N];
double dis2[N];
//L1 0 L2 n+1
double dis[N][N];
bool vis[N];
double low[N];
const double INF=0x3f3f3f3f;
double Dijkstra(){
int s=0;
int t=n+1;
for(int i=0;i<=n+1;i++){
low[i]=INF;
vis[i]=false;
}
low[s]=0;
for(int i=0;i<=n+1;i++){
int k=-1;
double Min=INF;
for(int j=0;j<=n+1;j++){
if(!vis[j] && low[j]<Min){
Min=low[j];
k=j;
}
}
if(k==-1){
break;
}
vis[k]=true;
for(int j=0;j<=n+1;j++){
if(!vis[j] && low[k]+dis[k][j]<low[j]){
low[j]=low[k]+dis[k][j];
}
}
}
return low[t];
}
int main(void){
scanf("%d%d%d%d%d",&n,&a,&b,&c1,&c2);
for(int i=1;i<=n;i++){
scanf("%d%d%d",&x[i],&y[i],&r[i]);
double t=abs(a*x[i]+b*y[i]+c1)*1.0/sqrt(a*a+b*b)-r[i];
if(t<0){
dis1[i]=0;
dis[0][i]=dis[i][0]=0;
}
else{
dis1[i]=t;
dis[0][i]=dis[i][0]=t;
}
t=abs(a*x[i]+b*y[i]+c2)*1.0/sqrt(a*a+b*b)-r[i];
if(t<0){
dis2[i]=0;
dis[n+1][i]=dis[i][n+1]=0;
}
else{
dis2[i]=t;
dis[n+1][i]=dis[i][n+1]=t;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
double t=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]))-r[i]-r[j];
if(t<0){
dis[i][j]=dis[j][i]=0;
}
else{
dis[i][j]=dis[j][i]=t;
}
}
}
dis[0][n+1]=dis[n+1][0]=abs(c1-c2)*1.0/sqrt(a*a+b*b);
// for(int i=0;i<=n+1;i++){
// for(int j=0;j<=n+1;j++){
// printf("%lf ",dis[i][j]);
// }
// printf("\n");
// }
printf("%.6lf\n",Dijkstra());
return 0;
}