思路:这题的难度主要是在建图上,建完图之后就是求单源最短路径问题。可用dijkstra算法.要注意他给出的墙的x坐标不是有序 的。
#include<stdio.h>
#include<math.h>
#include<string.h>
#define MAX 999
struct Position
{
double x;
double y;
}p[100];
double map[100][100],pos[20][5],dis[100];
int used[100],k;
bool solve(Position p1,Position p2,int bian)
{
if(p1.x==p2.x) //如果是一面墙上的点则不考虑
return false;
double left=p1.x<p2.x?p1.x:p2.x;
double right=p1.x>p2.x?p1.x:p2.x;
if(pos[bian][0]<=left||pos[bian][0]>=right) // 如果该墙不在这两点连线的范围之内则也不考虑
return true;
double a,b,posY;
a=(p1.y-p2.y)/(p1.x-p2.x);
b=p1.y-p1.x*a;
posY=a*pos[bian][0]+b;
if(posY>=pos[bian][1]&&posY<=pos[bian][2]||posY>=pos[bian][3]&&posY<=pos[bian][4])
return true;
return false;
}
double dist(Position p1,Position p2)
{
double res=sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
return res;
}
double djks(int s)
{
memset(used,0,sizeof(used));
double min;
int i,j,u;
for(i=0;i<=k;i++)
dis[i]=map[s][i];
dis[i]=0;
for(i=1;i<=k;i++)
{
min=MAX;
for(j=1;j<=k;j++)
{
if(used[j]!=1&&dis[j]<min)
{
min=dis[j];
u=j;
}
}
used[u]=1;
for(j=0;j<=k;j++)
{
if(used[j]!=1&&dis[u]+map[u][j]<dis[j])
{
dis[j]=dis[u]+map[u][j];
}
}
}
return dis[k];
}
int main()
{
int n,i,j,g;
double a,b;
while(scanf("%d",&n)&&n!=-1)
{
k=0;
p[k].x=0;
p[k++].y=5;
for(i=1;i<=n;i++)
{
scanf("%lf%lf%lf%lf%lf",&pos[i][0],&pos[i][1],&pos[i][2],&pos[i][3],&pos[i][4]); //将墙上的端点转化为点
p[k].x=pos[i][0];
p[k++].y=pos[i][1];
p[k].x=pos[i][0];
p[k++].y=pos[i][2];
p[k].x=pos[i][0];
p[k++].y=pos[i][3];
p[k].x=pos[i][0];
p[k++].y=pos[i][4];
}
p[k].x=10;
p[k].y=5;
for(i=0;i<=k;i++)
{
for(j=0;j<=k;j++)
{
map[i][j]=MAX;
}
}
for(i=0;i<=k;i++)
for(j=0;j<=k;j++)
{
for(g=1;g<=n;g++) //判断两点之间是否可以直接连通
{
if(!solve(p[i],p[j],g))
break;
}
if(g==n+1)
{
double d=dist(p[i],p[j]); //求两点距离
map[i][j]=d;
}
}
double res=djks(0);
printf("%.2lf\n",res);
}
return 0;
}
/*
1
5 4 6 7 8
2
4 2 7 8 9
7 3 4.5 6 7
-1
*/