#floyd,斜率#洛谷 1354 房间最短路问题

题目

在一个长宽均为10,入口出口分别为(0,5),(10,5)的房间里有几堵墙,
每堵墙上有两个缺口,求入口到出口的最短路径。


分析

暴力建图,判断两个点是否有墙堵住,
可以求斜率然后判断所交点不能在墙上
在这里,你甚至可以用floyd求单源最短路


代码

#include <cstdio>
#include <cmath>
#include <map>
#define rr register
#define o(x) ((x)*(x))
using namespace std;
typedef double db; typedef pair<db,db> pdd;
const pdd St=make_pair(0.0,5.0),Ed=make_pair(10.0,5.0);
struct five{db x,y[4];}a[21]; db dis[83][83];
int n,st,ed,CNT; map<pdd,int>uk;
inline void Min(db &x,db y){x=x<y?x:y;}
inline bool against(db Xx,db Xy,db Yx,db Yy,int pl,int pr){
	rr db K=(Yy-Xy)/(Yx-Xx),B=Xy-K*Xx;
	for (rr int i=pl;i<=pr;++i){
		rr db YY=K*a[i].x+B;
		if (YY<a[i].y[0]||(a[i].y[1]<YY&&YY<a[i].y[2])||a[i].y[3]<YY) return 1;
	}
	return 0;
}
inline void Check(db Xx,db Xy,db Yx,db Yy,int pl,int pr){
	if (against(Xx,Xy,Yx,Yy,pl,pr)) return;
	rr pdd t1=make_pair(Xx,Xy),t2=make_pair(Yx,Yy);
	if (!uk[t1]) uk[t1]=++CNT; if (t1==St) st=uk[t1];
	if (!uk[t2]) uk[t2]=++CNT; if (t2==Ed) ed=uk[t2];
	dis[uk[t1]][uk[t2]]=dis[uk[t2]][uk[t1]]=sqrt(o(Yx-Xx)+o(Yy-Xy));
}
signed main(){
	scanf("%d",&n);
	for (rr int i=1;i<83;++i)
	for (rr int j=1;j<83;++j)
	if (i!=j) dis[i][j]=1e9;
	for (rr int i=1;i<=n;++i)
	    scanf("%lf%lf%lf%lf%lf",&a[i].x,&a[i].y[0],&a[i].y[1],&a[i].y[2],&a[i].y[3]);
	Check(0.0,5.0,10.0,5.0,1,n); 
	for (rr int i=1;i<=n;++i)
	for (rr int j=0;j<4;++j)
	    Check(0.0,5.0,a[i].x,a[i].y[j],1,i-1),
	        Check(a[i].x,a[i].y[j],10.0,5.0,i+1,n);
	for (rr int i=1;i<n;++i) for (rr int i1=0;i1<4;++i1)
	for (rr int j=i+1;j<=n;++j) for (rr int j1=0;j1<4;++j1)
	    Check(a[i].x,a[i].y[i1],a[j].x,a[j].y[j1],i+1,j-1);
	for (rr int k=1;k<=CNT;++k)
	for (rr int i=1;i<=CNT;++i)
	for (rr int j=1;j<=CNT;++j)
	if (k!=i&&k!=j&&i!=j)
	    Min(dis[i][j],dis[i][k]+dis[k][j]);
	return !printf("%.2lf",dis[st][ed]);
}
posted @ 2020-10-03 01:58  lemondinosaur  阅读(75)  评论(0编辑  收藏  举报