描述
在一个长宽均为10,入口出口分别为(0,5)、(10,5)的房间里,有几堵墙,每堵墙上有两个缺口,求入口到出口的最短路经。
格式
输入格式
第一排为n(n<=20),墙的数目。
接下来n排,每排5个实数x,a1,b1,a2,b2。
x表示墙的横坐标(所有墙都是竖直的),a1-b1和a2-b2之间为空缺。
a1、b1、a2、b2保持递增,x1-xn也是递增的。
输出格式
输出最短距离,保留2位小数。
样例1
样例输入1
2
4 2 7 8 9
7 3 4.5 6 7
样例输出1
10.06
来源
Tsuzuki Matsumoto
From ZJU
N^3DP
最短路径肯定会经过一个端点,那么就枚举端点,然后判断中间是否可以连通就好了
貌似因为精度问题WA了一个点
解决方法就是不要用斜率,改成乘法就好了。。然而不想改了。。。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<bits/stdc++.h> 2 #define inf 1000000000 3 #define maxn 20+5 4 #define maxm 5000000+5 5 #define eps 1e-6 6 #define ll long long 7 #define mod 5000011 8 #define for0(i,n) for(int i=0;i<=(n);i++) 9 #define for1(i,n) for(int i=1;i<=(n);i++) 10 #define for2(i,x,y) for(int i=(x);i<=(y);i++) 11 #define for3(i,x,y) for(int i=(x);i>=(y);i--) 12 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go) 13 using namespace std; 14 int read(){ 15 int x=0,f=1;char ch=getchar(); 16 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 17 while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();} 18 return x*f; 19 } 20 struct wal{ 21 double x,a[3],b[3]; 22 }s[maxn]; 23 double f[maxn][6]; 24 int n; 25 double fabs(double x){ 26 if(x<0)return -x; 27 return x; 28 } 29 bool judge(double x,int j,double y1,double x1){ 30 for1(i,2){ 31 double k1=(y1-s[j].a[i])/(x1-s[j].x); 32 double k2=(y1-s[j].b[i])/(x1-s[j].x); 33 if(k2<x&&x<k1)return 1; 34 double t1=fabs(k1-x),t2=fabs(k2-x); 35 if(t1<=eps||t2<=eps)return 1; 36 } 37 return 0; 38 } 39 double cal(double y1,double x1,double y2,double x2){ 40 double t1=y2-y1,t2=x2-x1; 41 return sqrt(t1*t1+t2*t2); 42 } 43 int main(){ 44 //freopen("input.txt","r",stdin); 45 //freopen("output.txt","w",stdout); 46 n=read(); 47 int fl=0; 48 for1(i,n){ 49 cin>>s[i].x>>s[i].a[1]>>s[i].b[1]>>s[i].a[2]>>s[i].b[2]; 50 if(s[i].b[1]<=5&&5<=s[i].a[1])fl++; 51 if(s[i].b[2]<=5&&5<=s[i].a[2])fl++; 52 } 53 if(fl==n){ 54 printf("10.00"); 55 return 0; 56 } 57 for1(i,n) 58 for1(j,5) 59 f[i][j]=inf; 60 f[1][1]=cal(s[1].a[1],s[1].x,5,0); 61 f[1][2]=cal(s[1].b[1],s[1].x,5,0); 62 f[1][3]=cal(s[1].a[2],s[1].x,5,0); 63 f[1][4]=cal(s[1].b[2],s[1].x,5,0); 64 for2(i,2,n) 65 for1(c,2){ 66 for2(j,1,i-1) 67 for1(cc,2){ 68 double k1=(s[i].a[c]-s[j].a[cc])/(s[i].x-s[j].x); 69 double k2=(s[i].a[c]-s[j].b[cc])/(s[i].x-s[j].x); 70 double k3=(s[i].b[c]-s[j].a[cc])/(s[i].x-s[j].x); 71 double k4=(s[i].b[c]-s[j].b[cc])/(s[i].x-s[j].x); 72 int flag1=0,flag2=0,flag3=0,flag4=0; 73 for2(k,j+1,i-1){ 74 if(!judge(k1,k,s[i].a[c],s[i].x))flag1=1; 75 if(!judge(k2,k,s[i].a[c],s[i].x))flag2=1; 76 if(!judge(k3,k,s[i].b[c],s[i].x))flag3=1; 77 if(!judge(k4,k,s[i].b[c],s[i].x))flag4=1; 78 if(flag1+flag2+flag3+flag4==4)break; 79 } 80 if(!flag1)f[i][1+(c-1)*2]=min(f[i][1+(c-1)*2],f[j][1+(cc-1)*2]+cal(s[i].a[c],s[i].x,s[j].a[cc],s[j].x)); 81 if(!flag2)f[i][1+(c-1)*2]=min(f[i][1+(c-1)*2],f[j][2+(cc-1)*2]+cal(s[i].a[c],s[i].x,s[j].b[cc],s[j].x)); 82 if(!flag3)f[i][2+(c-1)*2]=min(f[i][2+(c-1)*2],f[j][1+(cc-1)*2]+cal(s[i].b[c],s[i].x,s[j].a[cc],s[j].x)); 83 if(!flag4)f[i][2+(c-1)*2]=min(f[i][2+(c-1)*2],f[j][2+(cc-1)*2]+cal(s[i].b[c],s[i].x,s[j].b[cc],s[j].x)); 84 } 85 double k1=(s[i].a[c]-5)/(s[i].x); 86 double k2=(s[i].b[c]-5)/(s[i].x); 87 int flag1=0,flag2=0; 88 for1(k,i-1){ 89 if(!judge(k1,k,s[i].a[c],s[i].x))flag1=1; 90 if(!judge(k2,k,s[i].b[c],s[i].x))flag2=1; 91 if(flag1+flag2==2)break; 92 } 93 if(!flag1)f[i][1+(c-1)*2]=min(f[i][1+(c-1)*2],cal(s[i].a[c],s[i].x,5,0)); 94 if(!flag2)f[i][2+(c-1)*2]=min(f[i][2+(c-1)*2],cal(s[i].b[c],s[i].x,5,0)); 95 } 96 double ans=inf; 97 for1(j,n) 98 for1(cc,2){ 99 double k1=(5-s[j].a[cc])/(10-s[j].x); 100 double k2=(5-s[j].b[cc])/(10-s[j].x); 101 int flag1=0,flag2=0; 102 for2(k,j+1,n){ 103 if(!judge(k1,k,5,10))flag1=1; 104 if(!judge(k2,k,5,10))flag2=1; 105 if(flag1+flag2==2)break; 106 } 107 if(!flag1)ans=min(ans,f[j][1+(cc-1)*2]+cal(5,10,s[j].a[cc],s[j].x)); 108 if(!flag2)ans=min(ans,f[j][2+(cc-1)*2]+cal(5,10,s[j].b[cc],s[j].x)); 109 } 110 printf("%.2lf",ans); 111 return 0; 112 }