题意:
从(0,5)到(10,5)中间有n堵墙,每个墙会开两个门。求从(0,5)到(10,5)的最短距离。n <= 18。
题解:
1.起点、终点、每个门的两个端点都看作一个点,先通过判断线段相交来求出点与点的初始距离(不用拐弯的距离)。这个题因为一条线段是垂直于x轴的,判断与另一条线段是否相交就简单了。
2.在第1步求出点与点的初始距离后直接套用dijkstra模板求最短路就ok了。
3.一直WA是因为特判n=0输出10,其实应该是10.00,脑子当时秀逗了。。。。。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
using namespace std ;
#define eps 1e-8
struct Door
{
double x , y[50] ;
} door[200] ;
struct Node
{
double x , y ;
} node[500] ;
int n , cnt ;
double dis[500] ;
double map1[500][500] ;
bool in(int a , int b , double x1 , double y1 , double x2 , double y2)
{
double k1 = (y2 - y1) / (x2 - x1) ;
double b1 = y1 - k1 * x1 ;
double y = k1 * door[a].x + b1 ;
if(y >= door[a].y[b * 2 - 1] && y <= door[a].y[b * 2]
|| fabs(y - door[a].y[b * 2 - 1]) < eps
|| fabs(y - door[a].y[b * 2]) < eps )
return 1 ;
return 0 ;
}
bool canlink(int a , int b , int c , int d)
{
int i , j , k ;
double x1 , y1 , x2 , y2 ;
bool flag ;
if(a == -1)
{
x1 = 0 ;
y1 = 5 ;
}
else
{
x1 = door[a].x ;
y1 = door[a].y[b] ;
}
if(c == n)
{
x2 = 10 ;
y2 = 5 ;
}
else
{
x2 = door[c].x ;
y2 = door[c].y[d] ;
}
for(i = a + 1 ; i < c ; i ++)
{
flag = 0 ;
if(in(i , 1 , x1 , y1 , x2 , y2))
flag = 1 ;
if(in(i , 2 , x1 , y1 , x2 , y2))
flag = 1 ;
if(!flag)
return 0 ;
}
return 1 ;
}
void judge()
{
int i , j , p , q ;
int a , b ;
double x1 , y1 , x2 , y2 ;
for(i = -1 ; i <= n - 1 ; i ++)
for(j = i + 1 ; j <= n ; j ++)
for(p = 1 ; p <= 4 ; p ++)
for(q = 1 ; q <= 4 ; q ++)
if(canlink(i , p , j , q))
{
if(i == -1)
{
a = 0 ;
x1 = 0 ;
y1 = 5 ;
}
else
{
a = i * 4 + p ;
x1 = door[i].x ;
y1 = door[i].y[p] ;
}
if(j == n)
{
b = cnt - 1 ;
x2 = 10 ;
y2 = 5 ;
}
else
{
b = j * 4 + q ;
x2 = door[j].x ;
y2 = door[j].y[q] ;
}
map1[a][b] = map1[b][a] = sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)) ;
}
}
void dijkstra()
{
int i , j , k ;
bool vis[500] ;
double min1 ;
int temp ;
memset(vis , 0 , sizeof(vis)) ;
dis[0] = 0 ;
for(i = 1 ; i < cnt ; i ++)
dis[i] = map1[0][i] ;
for(i = 0 ; i < cnt - 1 ; i ++)
{
min1 = 10000 ;
temp = -1 ;
for(j = 0 ; j < cnt ; j ++)
if(!vis[j] && dis[j] < min1 && fabs(dis[j] - min1) > eps)
{
min1 = dis[j] ;
temp = j ;
}
vis[temp] = 1 ;
for(j = 0 ; j < cnt ; j ++)
dis[j] = min(dis[j] , dis[temp] + map1[temp][j]) ;
}
}
int main()
{
int i , j ;
while(scanf("%d" , &n) && n != -1)
{
if(n == 0)
{
printf("10.00\n") ;
continue ;
}
cnt = 0 ;
for(i = 0 ; i < n ; i ++)
{
scanf("%lf" , &door[i].x) ;
for(j = 1 ; j <= 4 ; j ++)
scanf("%lf" , &door[i].y[j]) ;
}
cnt = 4 * n + 2 ;
for(i = 0 ; i < cnt ; i ++)
for(j = 0 ; j < cnt ; j ++)
map1[i][j] = 10000 ;
judge() ; //判断哪两个点可以相连。
dijkstra() ; //跑一遍最短路模板
printf("%.2f\n" , dis[cnt - 1]) ;
}
}