comet OJ 热身赛 dijkstra

题目链接:comet OJ 热身赛 dijkstra

题目描述

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=ri​2。角色在直线上、圆上、圆内行走不消耗体力。在其他位置上由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

对题目的理解:

怎么抽象成迪杰斯特拉?

我们可以将第一条边当成图里的源点,然后计算任意一个圆与两条直线的距离,与剩下所有圆的距离

对于图的存储,我们的二维数组中的每一个元素都会重新赋值

在存图前的准备工作是计算:

  • 两条直线间的距离
  • 圆与圆之间的距离
  • 圆与直线间的距离

两直线间的距离公式:《comet OJ 热身赛 dijkstra》

点到直线距离公式:
设直线 L 的方程为Ax+By+C=0,点 P 的坐标为(Xo,Yo),则点 P 到直线 L 的距离为:

 《comet OJ 热身赛 dijkstra》

 

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
---
*/
 
 
 

《comet OJ 热身赛 dijkstra》

 

 

 

 

 

    原文作者:Dijkstra算法
    原文地址: https://blog.csdn.net/Helloirbd/article/details/86560359
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞