Wannafly summer camp Day2 L New Game!

題目描述:

Eagle Jump公司正在開發一款新的遊戲。瀧本一二三作爲其員工,獲得了提前試玩的機會。現在她正在試圖通過一個迷宮。

這個迷宮有一些特點。爲了方便描述,我們對這個迷宮建立平面直角座標系。迷宮中有兩條平行直線 L1:Ax+By+C=0, L2:Ax+By+C2=0,還有 n 個圓 Ci:(x−xi)^2+(y−yi)^2=ri^2。角色在直線上、圓上、圓內行走不消耗體力。在其他位置上由S點走到T點消耗的體力爲S和T的歐幾里得距離。

瀧本一二三想從 L1出發,走到 L2 。請計算最少需要多少體力。

輸入:

第一行五個正整數 n,A,B,C1,C2(1≤n≤1000,−10000≤A,B,C1,C2≤10000),其中 A,BA,BA,B 不同時爲 0。

接下來 n 行每行三個整數 x,y,r(−10000≤x,y≤10000,1≤r≤10000)表示一個圓心爲 (x,y),半徑爲 r的圓。

輸出:

僅一行一個實數表示答案。與標準答案的絕對誤差或者相對誤差不超過 10^(-4) 即算正確。

樣例輸入

2 0 1 0 -4
0 1 1
1 3 1

樣例輸出

0.236068

 

 

解題思路:把圓(1~n)和兩條直線(n+1和n+2)當作節點,然後求從n+1出發到n+2的最短距離。

分三種情況討論:

直線與直線:距離爲c1-c2的絕對值

直線與圓:圓心到直線的距離與圓的半徑進行比較

圓與圓:圓心之間的距離與兩個圓的半徑進行比較

然後跑一遍spfa就行

/*************************************************************************
	> File Name: 2075: New Game!(*)  .cpp
	> Author: baozi
	> Last modified: 2018年08月06日 星期一 13時58分
	> status:AC 
 ************************************************************************/
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<queue>
using namespace std;
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn=1e3+20;
const int inf=0x3f3f3f3f;
int n,m,t,a,b,c1,c2,vis[maxn];
double dis[maxn];
struct Node{
	double x,y,r;
}node[maxn];
double find(int a1,int b1){
	if(a1>n&&b1>n){
		return c1 -c2;
	}
	else if((a1>n&&b1<=n)||(a1<=n&&b1>n)){
		if(b1>n) swap(a1,b1);
		if(a1==n+1){
			double t=a*node[b1].x+b*node[b1].y+c1;
			if(t<0) t=-t; 
			double k=sqrt(a*a+b*b);
			t/=k;
			if(t<=node[b1].r) return 0;
			else return t-node[b1].r; 
		}
		else{
			double t=a*node[b1].x+b*node[b1].y+c2;
			if(t<0) t=-t; 
			double k=sqrt(a*a+b*b);
			t/=k;
			if(t<=node[b1].r) return 0;
			else return t-node[b1].r; 
		}
	}
	else{
		double x1=node[a1].x-node[b1].x;
		double y1=node[a1].y-node[b1].y;
		double k=sqrt(x1*x1+y1*y1);
		if(k<=node[a1].r+node[b1].r) return 0;
		else return k-node[a1].r-node[b1].r;
	}
}
void spfa(){
	mem(vis,0);
	for(int i=1;i<=n+2;i++) dis[i]=inf;
	dis[n+1]=0;vis[n+1]=1;
	queue<int> qu;
	qu.push(n+1);
	while(!qu.empty()){
		int u=qu.front();qu.pop();vis[u]=0;
		for(int i=1;i<=n+2;i++){
			double t=find(u,i);
			if(dis[i]>dis[u]+t){
				dis[i]=dis[u]+t;
				if(!vis[i]){
					vis[i]=1;qu.push(i);
				}
			}
		}
	}
}
int main(){
	int i,j;
	scanf("%d%d%d%d%d",&n,&a,&b,&c1,&c2);
	if(c1<c2) swap(c1,c2);
	for(i=1;i<=n;i++){
		scanf("%lf%lf%lf",&node[i].x,&node[i].y,&node[i].r);
	}
	spfa();
	printf("%.6lf\n",dis[n+2]);
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章