题目链接:点击打开链接
题目大意:给你一个起点一个终点,然后给你一堆圆的坐标和半径,你可以躲在圆里面,问你从起点到终点的最短距离(在圆内不算距离)
题目思路:太菜了压根没想到是最短路..其实很明显的..如果两个圆的半径相加大于等于两个圆心直接的距离,那这两个圆里面随便走都不算距离。如果小于的话,只用算圆心之间的距离减去两个圆的半径就行了,起点和终点的半径自然就是0了,然后就能求出各个点之间的距离,迪杰斯特拉板子一套直接就过了,主要是没想到这个思路..QAQ
以下是代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<math.h>
using namespace std;
#define MAXN 1005
#define inf 999999999.0
double xs,ys,xt,yt;
struct node{
double x,y,r;
}a[MAXN];
int vis[MAXN];
double dis[MAXN],map1[MAXN][MAXN];
int main(){
while(~scanf("%lf%lf%lf%lf",&xs,&ys,&xt,&yt)){
int n;
scanf("%d",&n);
a[0].x=xs,a[0].y=ys,a[n+1].x=xt,a[n+1].y=yt;
for(int i=1;i<=n;i++){
scanf("%lf%lf%lf",&a[i].x,&a[i].y,&a[i].r);
}
memset(vis,0,sizeof(vis));
for(int i=0;i<=n+1;i++){
for(int j=0;j<=n+1;j++){
if(i==j){
map1[i][j]=0.0;
}
else{
double ju=sqrt((a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y));
if(ju<=a[i].r+a[j].r){
map1[i][j]=0.0;
map1[j][i]=0.0;
}
else{
map1[i][j]=ju-a[i].r-a[j].r;
map1[j][i]=ju-a[i].r-a[j].r;
}
}
}
}
for(int i=0;i<=n+1;i++){
dis[i]=map1[0][i];
}
vis[0]=1;
for(int i=0;i<n+1;i++){
double minn=inf;
int u;
for(int j=0;j<=n+1;j++){
if(!vis[j]&&dis[j]<minn){
minn=dis[j];
u=j;
}
}
vis[u]=1;
for(int j=0;j<=n+1;j++){
if(dis[j]>dis[u]+map1[u][j]){
dis[j]=dis[u]+map1[u][j];
}
}
}
printf("%.9lf\n",dis[n+1]);
}
return 0;
}