给一个房间,房间的边都是固定的,房间内有一些墙, 每面墙上有两个门, 起点是(0,5) 终点是(5,0), 求起点到终点的最短路径( 遇到墙从门走)
解题思路: 想到怎么 建图就好做了
N条边则有4*N+1个顶点, 我们所要求的就是怎样连接这些定点使得起点到终点的距离最小
因为N最多是10,所以这道题完全可以暴力算点和点之间的距离,然后用 DIJ, 在建图的时候我们要注意 ,如果两个点连线跟门有交点, 那就意味着可以直接连接这两个点,并且根据题给要求得知相交一定是完全相交,
用DIJ 的时候也要注意当松弛的时候得到的最小距离是起点到终点的最小距离那么直接返回就好了
PS 不知道为啥C++交就对G++就WA
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <cmath>
#include <stdlib.h>
using namespace std;
#define MAXP 555
#define MAXL 111
#define eps 1e-8
#define INF 100000000
double dis[MAXP], gra[MAXP][MAXP];
bool vis[MAXP];
struct Point
{
double x,y;
Point(){};
Point(double a, double b)
{
x = a;
y = b;
}
}p[MAXP];
struct Line
{
Point s, e;
Line(){};
Line(Point a, Point b)
{
s = a;
e = b;
}
}l[MAXL];
int sig(double a)
{
if(a < -eps)
return -1;
if(a > eps)
return 1;
return 0;
}
double Across(Point a, Point b, Point c)
{
return (b.x - a.x)*(c.y - a.y) - (b.y - a.y)*(c.x - a.x);
}
double getdis(Point a, Point b)
{
return sqrt((a.x - b.x)*(a.x- b.x) + (a.y - b.y) * (a.y - b.y));
}
bool SegAcorss(Point a, Point b, Point c, Point d)
{
int d1, d2, d3, d4;
d1 = sig(Across(a, b, c));
d2 = sig(Across(a, b, d));
d3 = sig(Across(c, d, a));
d4 = sig(Across(c, d, b));
if(d1*d2 == -1 && d3*d4 == -1)
return true;
return false;
}
void solve(int pn, int ln)
{
for( int i = 0; i <= pn; i++)
for( int j = 0; j <= pn; j++)
gra[i][j] = INF;
for(int i = 0; i <= pn; i++)
{
for(int j = i + 1; j <= pn; j++)
{
bool flag = 1;
for(int k = 0; k < ln && flag; k += 2)
{
int t = 0,f[2] = {0};
if(p[i].x < l[k].s.x && p[j].x > l[k].s.x)
{
f[0] = SegAcorss(p[i],p[j], l[k].s, l[k].e);
f[1] = SegAcorss(p[i],p[j], l[k + 1].s, l[k+1].e);
t++;
}
if(t)
flag = f[0]|f[1];
}
if(flag)
gra[i][j] = getdis(p[i],p[j]);
}
}
}
double dij( int N )//求最短路
{
for( int i = 0 ; i <= N ; i ++ )
{
vis[i] = false;
dis[i] = 100000000;
}
dis[0] = 0;
for( int i = 0 ; i < N ; i++ )
{
double min = 100000000;
int t;
for( int j = 0 ; j <= N ; j ++ )
{
if( !vis[j] && min > dis[j] )
{
min = dis[j] ; t = j;
}
}
if( t==N ) return dis[N];
vis[t] = true;
for( int j = 0 ; j <= N ; j ++ )
{
if( !vis[j] && gra[t][j] != INF && dis[j] > dis[t] + gra[t][j] )
dis[j] = dis[t] + gra[t][j];
}
}
return dis[N];
}
int main()
{
int n;
double a,b,c,d,e;
while(scanf("%d",&n)!= EOF && n != -1)
{
p[0].x = 0, p[0].y = 5;
p[4*n+1].x = 10, p[4*n+1].y = 5;
int lcnt = 0;
for(int i = 0; i < n; i++)
{
scanf("%lf %lf %lf %lf %lf",&a, &b, &c, &d, &e);
p[4*i + 1] = Point(a, b);
p[4*i + 2] = Point(a, c);
p[4*i + 3] = Point(a, d);
p[4*i + 4] = Point(a, e);
l[lcnt++] = Line(Point(a,b), Point(a,c));
l[lcnt++] = Line(Point(a,d), Point(a,e));
}
solve(4*n + 1, lcnt);
printf("%.2lf\n",dij(4*n+1));
}
return 0;
}