题目描述
Eagle Jump公司正在开发一款新的游戏。泷本一二三作为其员工,获得了提前试玩的机会。现在她正在试图通过一个迷宫。
这个迷宫有一些特点。为了方便描述,我们对这个迷宫建立平面直角坐标系。迷宫中有两条平行直线 L_1:Ax+By+C_1=0L1:Ax+By+C1=0, L_2:Ax+By+C_2=0L2:Ax+By+C2=0,还有 nn 个圆 C_i:(x-x_i)^2+(y-y_i)^2={r_i}^2Ci:(x−xi)2+(y−yi)2=ri2。角色在直线上、圆上、圆内行走不消耗体力。在其他位置上由SS点走到TT点消耗的体力为SS和TT的欧几里得距离。
泷本一二三想从 L_1L1 出发,走到 L_2L2 。请计算最少需要多少体力。
输入描述
第一行五个正整数 n,A,B,C_1,C_2n,A,B,C1,C2 (1\le n \le 1000, -10000 \le A,B,C_1,C_2 \le 10000)(1≤n≤1000,−10000≤A,B,C1,C2≤10000),其中 A,BA,B 不同时为 0。
接下来 nn 行每行三个整数 x,y,r(-10000 \le x,y \le 10000, 1\le r \le 10000)x,y,r(−10000≤x,y≤10000,1≤r≤10000) 表示一个圆心为 (x,y)(x,y),半径为 rr 的圆。
输出描述
仅一行一个实数表示答案。与标准答案的绝对误差或者相对误差不超过 10^{-4}10−4 即算正确。
样例输入 1
2 0 1 0 -4 0 1 1 1 3 1
样例输出 1
0.236068
对题目的理解:
怎么抽象成迪杰斯特拉?
我们可以将第一条边当成图里的源点,然后计算任意一个圆与两条直线的距离,与剩下所有圆的距离
对于图的存储,我们的二维数组中的每一个元素都会重新赋值
在存图前的准备工作是计算:
- 两条直线间的距离
- 圆与圆之间的距离
- 圆与直线间的距离
两直线间的距离公式:
点到直线距离公式:
设直线 L 的方程为Ax+By+C=0,点 P 的坐标为(Xo,Yo),则点 P 到直线 L 的距离为:
AC代码:
#include<iostream>
#include<cstring>
#include<math.h>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn=1010;
const double INF=10000000;
typedef pair<int ,int > P;
double mp[maxn][maxn];
bool vis[maxn];
double dis[maxn];
int n;
struct Cir{
int x;//横坐标
int y;//纵坐标
int r;//半径
};
Cir c[maxn];
void Init(){
memset(vis,0,sizeof(vis));
for(int i=0;i<=maxn;i++){
dis[i]=999999999;
}
for(int i=0;i<=n;i++){
for(int j=0;j<=n;j++){
if(i==j){
mp[i][j]=0;
}
}
}
}
double LL(int A,int B,int C1,int C2){//求两直线之间的距离
return (double)fabs(C1-C2)/sqrt((double)(A*A+B*B));
}
double CL(int x1,int y1,int r,int A,int B,int C){//求圆与直线之间的距离
double d=(double)fabs(A*x1+B*y1+C)/sqrt((double)(A*A+B*B));
if(r>d){
return 0;
}else{
return d-r;
}
}
double CC(int x1,int y1,int r1,int x2,int y2,int r2){//求两圆之间的距离
double d;
d=sqrt((double)((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)));
if(d<(r1+r2)){
return 0;
}else{
//cout<<d-r1-r2<<'*'<<endl;
return d-r1-r2;
}
}
void dijkstra(){
priority_queue<P,vector<P>,greater<P> > que;
dis[0]=0;
que.push(P(dis[0],0));
while(!que.empty()){
P p=que.top();
que.pop();
int k=p.second;
vis[k]=1;
for(int i=0;i<=n+1;i++){
// cout<<"&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"<<endl;
// cout<<"k="<<k<<endl;
// cout<<"dis["<<i<<"]="<<dis[i]<<endl;
// cout<<"mp["<<k<<"]["<<i<<"]+dis["<<k<<"]"<<endl;
// cout<<mp[k][i]<<'+'<<dis[k]<<'='<<mp[k][i]+dis[k]<<endl;
if(!vis[i]&&dis[i]>mp[k][i]+dis[k]){
dis[i]=mp[k][i]+dis[k];
//cout<<"dis["<<i<<"]=mp["<<k<<"]["<<i<<"]+dis["<<k<<"]"<<endl;
//cout<<"dis["<<i<<"]="<<dis[i]<<endl;
que.push(P(dis[i],i));
}
}
}
cout<<dis[n+1];
}
int main(){
Init();
int A,B,C1,C2;
cin>>n>>A>>B>>C1>>C2;
// for(int i=0;i<=n+1;i++){
// cout<<dis[i]<<'!'<<endl;
// }
mp[0][0]=0;
mp[n+1][n+1]=0;
mp[0][n+1]=mp[n+1][0]=LL(A,B,C1,C2);
for(int i=1;i<=n;i++){
cin>>c[i].x>>c[i].y>>c[i].r;
}
//cout<<"**********************"<<endl;
for(int i=1;i<=n;i++){
//cout<<"##############"<<endl;
for(int j=1;j<i;j++){
//cout<<"$$$$"<<endl;
mp[i][j]=mp[j][i]=(CC(c[i].x,c[i].y,c[i].r,c[j].x,c[j].y,c[j].r));
//cout<<mp[i][j]<<'&';
}
mp[0][i]=mp[i][0]=(CL(c[i].x,c[i].y,c[i].r,A,B,C1));
mp[i][n+1]=mp[n+1][i]=CL(c[i].x,c[i].y,c[i].r,A,B,C2);
}//存图
// for(int i=0;i<=n+1;i++){
// for(int j=0;j<=n+1;j++){
// cout<<mp[i][j]<<' ';
// }
// cout<<endl;
// }
dijkstra();
}
/*
2 0 1 0 -4
0 1 1
1 3 1
0 0 2 4
0 0 0 2
2 0 0 0
4 2 0 0
0
---
*/