一道图论和计算几何综合的题
题意很好理解,略
【解答】
把墙上的所有可以走的点作为图中的点,建边的时候用线段相交判断是否可以连边。
在跑一次dijkstra即可得解。注意,线段相交的时候,端点不算。
水题,可以作为练手的题。
#include <iostream>
#include <cmath>
#define eps 1e-8
using namespace std;
const int maxn=300;
const double oo=1e8;
struct point
{
double x,y;
}p[maxn];
struct line
{
point a,b;
}w[maxn];
double a[maxn][maxn],d[maxn];
int v[maxn];
int tot,ss,n;
double xmult(point p1,point p2,point p0)
{
return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
double dist(point a,point b)
{
return sqrt(double((b.x-a.x)*(b.x-a.x)+(b.y-a.y)*(b.y-a.y)));
}
int opposite_side(point p1,point p2,point l1,point l2)
{
return xmult(p1,l2,l1)*xmult(p2,l2,l1)<-eps;
}
int intersect_ex(point u1,point u2,point v1,point v2)
{
return opposite_side(u1,u2,v1,v2) && opposite_side(v1,v2,u1,u2);
}
void init()
{
p[0].x=0;p[0].y=5;
for (int i=0;i<n;i++)
{
double xx,a,b,c,d;
cin >> xx >> a >> b >> c >> d;
w[tot].a.x=xx;w[tot].a.y=0;w[tot].b.x=xx;w[tot++].b.y=a;
w[tot].a.x=xx;w[tot].a.y=b;w[tot].b.x=xx;w[tot++].b.y=c;
w[tot].a.x=xx;w[tot].a.y=d;w[tot].b.x=xx;w[tot++].b.y=10;
p[ss].x=xx;p[ss++].y=a;
p[ss].x=xx;p[ss++].y=b;
p[ss].x=xx;p[ss++].y=c;
p[ss].x=xx;p[ss++].y=d;
}
p[ss].x=10;p[ss].y=5;
}
void build()
{
int i,j,k,ff;
for (i=0;i<=ss;i++)
for (j=0;j<=ss;j++)
if (i==j) a[i][j]=0;
else a[i][j]=oo;
for (i=0;i<=ss;i++)
for (j=0;j<=ss;j++)
{
if (i==j) continue;
ff=1;
for (k=0;k<tot;k++)
if (intersect_ex(p[i],p[j],w[k].a,w[k].b))
ff=0;
if (ff) a[i][j]=dist(p[i],p[j]);
}
}
double dijkstra()
{
double mi;
int i,k;
for (i=0;i<=ss;i++)
d[i]=oo,v[i]=0;
d[0]=0;
while (1)
{
k=-1;mi=oo;
for (i=0;i<=ss;i++)
if (d[i]<mi && !v[i])
mi=d[i],k=i;
if (k==-1) break;
v[k]=1;
for (i=0;i<=ss;i++)
if (d[k]+a[k][i]<d[i])
d[i]=d[k]+a[k][i];
}
return d[ss];
}
int main()
{
freopen("pin.txt","r",stdin);
freopen("pou.txt","w",stdout);
while (cin >> n && n!=-1)
{
tot=0,ss=1;
init();
build();
cout.precision(2);
cout.setf(ios_base::floatfield,ios_base::fixed);
cout << dijkstra() << endl;
}
return 0;
}