POJ 1556 The Doors 最短路floyd + 判断两线段相交

构建模型非常重要。

建图:把起点,终点,每个墙上的4个点分别看成图的顶点;

把这些点中各对点连起来,如果与墙相交(判断两线段相交)则不连,然后floyd暴力一下。

 

思路想到了就蛮清晰的,但我刚学计算几何,一直很纠结点写成结构体还是分开来写,调用的时候哪个比较方便,总觉得2个都很麻烦,诶,所以荒废了比较多的时间,以后不能这么2了。

 

然后我把2种都写了一遍,写计算几何一定要注意规范。

 

代码1:(函数调入点用double)

View Code
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#define eps 10e-8
#define inf 1<<29
using namespace std;
struct point
{
    double x, y;
};

int n;
double xx[22], yy[22][5];
point p[90];
double adj[90][90];
int psize;

double ff(double x)
{
    return x*x;
}
double dis(point p1, point p2)
{
    return sqrt(ff(p1.x - p2.x) + ff(p1.y - p2.y));
}
double cross(double x1, double y1, double x2, double y2, double x3, double y3)
{
    return (x2 - x1)*(y3 - y1) - (y2 - y1)*(x3 - x1);
}
bool judge(point p1, point p2)
{
    if(p1.x >= p2.x)return 0;
    int i = 0;
    while(xx[i] <= p1.x && i < n)i++;
    while(xx[i] < p2.x && i < n)
    {
        if(cross(p1.x, p1.y, p2.x, p2.y, xx[i], 0)*cross(p1.x, p1.y, p2.x, p2.y, xx[i], yy[i][1])<0
         ||cross(p1.x, p1.y, p2.x, p2.y, xx[i], yy[i][2])*cross(p1.x, p1.y, p2.x, p2.y, xx[i], yy[i][3])<0
         ||cross(p1.x, p1.y, p2.x, p2.y, xx[i], yy[i][4])*cross(p1.x, p1.y, p2.x, p2.y, xx[i], 10)<0)
         return 0;
        i++;
    }
    return 1;
}
void floyd()
{
    int i, j, k;
    for(k=0;k<psize;k++)
        for(i=0;i<psize;i++)
            for(j=i+1;j<psize;j++)
                if(i!=k && j!=k)
                    adj[i][j]=min(adj[i][j], adj[i][k] + adj[k][j]);
    printf("%.2f\n",adj[0][psize - 1]);
}
int main()
{
    int i, j;
    while(~scanf("%d",&n)&&n!=-1)
    {
        p[0].x = 0; p[0].y = 5;psize=1;
        for(i=0;i<n;i++)
        {
            scanf("%lf",&xx[i]);
            for(j=1;j<=4;j++)
            {
                p[psize].x = xx[i];
                scanf("%lf",&p[psize].y);
                yy[i][j] = p[psize].y;
                psize++;
            }
        }
        p[psize].x = 10; p[psize].y = 5;
        psize++;
        for(i=0;i<psize;i++)
            for(j=0;j<psize;j++)
                adj[i][j] = inf;
        for(i=0;i<psize;i++)
            for(j=i+1;j<psize;j++)
                if(judge(p[i], p[j]))
                    adj[i][j] = dis(p[i], p[j]);
        floyd();
    }
    return 0;
}


代码2:(函数调入点用point)

View Code
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
#define inf 1<<29
#define eps 10e-8
#define f(x) (x)*(x)
struct point
{
    double x, y;
};

double xx[22], yy[22][5];
double adj[90][90];
point p[90];
int psize;
int n;

double dis(point p1, point p2)
{
    return sqrt(f(p1.x - p2.x) + f(p1.y  -p2.y));
}

double cross(point p0,point p1, point p2)//叉积
{
    return (p1.x - p0.x)*(p2.y - p0.y) - (p1.y - p0.y)*(p2.x - p0.x);
}

bool line_cross(point p1, point p2, point p3, point p4)//判断两线段相交
{
    if(cross(p1, p2, p3)*cross(p1, p2, p4) > eps)return 0;
    return 1;
}

bool judge(point p1, point p2)
{
    if(p1.x >= p2.x)return 0;
    int i = 1;
    while(xx[i] <= p1.x && i <= n)i++;
    while(xx[i] < p2.x && i <= n)
    {
        point pp1, pp2, pp3, pp4, pp5, pp6;
        pp1.x = pp2.x = pp3.x = pp4.x = pp5.x = pp6.x = xx[i];
        pp1.y = 0; pp2.y = yy[i][1]; pp3.y = yy[i][2]; pp4.y = yy[i][3]; pp5.y = yy[i][4];pp6.y = 10;
        if(line_cross(p1, p2, pp1, pp2) || line_cross(p1, p2, pp3, pp4) || line_cross(p1, p2, pp5, pp6))
            return 0;
        i++;
    }
    return 1;
}

void floyd()
{
    int i, j, k;
    for(k=0;k<psize;k++)
        for(i=0;i<psize;i++)
            for(j=i+1;j<psize;j++)
                if(k!=i && k!=j)
                    adj[i][j] = min (adj[i][j], adj[i][k] + adj[k][j]);
    printf("%.2f\n", adj[0][psize-1]);
}

int main()
{
    int i, j;
    while(~scanf("%d",&n) && n != -1)
    {
        p[0].x = 0; p[0].y = 5;psize=1;
        for(i=1;i<=n;i++)
        {
            scanf("%lf",&xx[i]);
            for(j=1;j<=4;j++)
            {
                p[psize].x = xx[i];
                scanf("%lf",&yy[i][j]);
                p[psize].y = yy[i][j];
                psize++;
            }
        }
        p[psize].x = 10; p[psize].y = 5;psize++;
        for(i = 0;i < psize; i++)
            for(j = 0;j < psize; j++)
                adj[i][j] = inf;
        for(i=0;i<psize;i++)
            for(j=i+1;j<psize;j++)
                if(judge(p[i], p[j]))
                    adj[i][j] = dis(p[i], p[j]);
        floyd();
    }
    return 0;
}

 

posted @ 2012-08-16 19:02  To be an ACMan  Views(409)  Comments(0)    收藏  举报