poj 1556 The Doors

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iomanip>

using namespace std;

const int INF = 100000000;
const int MAXN = 100;

struct Point
{
    double x;
    double y;
};

struct Edge
{
    int u;
    int v;
};

int n;
double WallX[20];
Point pDoor[MAXN];
int pNum;
double pY[20][4];
double g[MAXN][MAXN];

Edge edges[MAXN * MAXN];
int eNum;
int i, j;

double Dis(Point a, Point b)
{
    return sqrt( (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)  );
}

double Judge(double x1, double y1, double x2, double y2, double x3, double y3)
{
    return ((y3 - y1) * (x2 - x1) - (y2 - y1) * (x3 - x1));
}

bool CanConnect(Point a, Point b)
{
    if(a.x >= b.x)
        return false;
    bool flag = true;
    int i = 0;
    while(WallX[i] <= a.x && i < n)
        i++;
    while(WallX[i] < b.x && i < n)
    {
        if(Judge(a.x, a.y, b.x, b.y, WallX[i], 0) * Judge(a.x, a.y, b.x, b.y, WallX[i], pY[i][0]) < 0
           || Judge(a.x, a.y, b.x, b.y, WallX[i], pY[i][1]) * Judge(a.x, a.y, b.x, b.y, WallX[i], pY[i][2]) < 0
           || Judge(a.x, a.y, b.x, b.y, WallX[i], pY[i][3]) * Judge(a.x, a.y, b.x, b.y, WallX[i], 10) < 0
           )
        {
            flag = false;
            break;
        }
        i++;
    }
    return flag;
}

double Bellman_Ford(int Start, int End)
{
    double dist[MAXN];
    int i, j;
    for(i = 0; i < MAXN; ++i)
        dist[i]  = INF;
    dist[Start] = 0;
    bool flag = true;
    for(i = 0; i < pNum && flag; ++i)
    {
        flag = false;
        for(j = 0; j < eNum; ++j)
        {
            if(dist[edges[j].u] < INF && dist[edges[j].v] > dist[edges[j].u] + g[edges[j].u][edges[j].v])
            {
                dist[edges[j].v] = dist[edges[j].u] + g[edges[j].u][edges[j].v];
                flag = true;
            }
        }
    }
    return dist[End];
}


void ReadCase()
{
    int i, j;
    pDoor[0].x = 0;
    pDoor[0].y = 5;
    pNum = 1;
    for(i = 0; i < n; ++i)
    {
        cin>>WallX[i];
        for(j = 0; j < 4; ++j)
        {
            pDoor[pNum].x = WallX[i];
            cin >> pDoor[pNum].y;
            pY[i][j] = pDoor[pNum].y;
            pNum++;
        }
    }
    pDoor[pNum].x = 10;
    pDoor[pNum].y = 5;
    pNum++;
    for(i = 0; i < pNum; ++i)
    {
        for(j = 0; j < pNum; ++j)
        {
            g[i][j] = INF;
        }
    }
    eNum = 0;
    for(i = 0; i < pNum; ++i)
    {
        for(j = i+1; j < pNum; ++j)
        {
            if(CanConnect(pDoor[i], pDoor[j]))
            {
                g[i][j] = Dis(pDoor[i], pDoor[j]);
                edges[eNum].u = i;
                edges[eNum].v = j;
                eNum++;
            }
        }
    }
    cout<<setiosflags(ios::fixed)<<setprecision(2)<<Bellman_Ford(0, pNum-1)<<endl;
}

int main()
{
    while(cin>>n)
    {
        if(n == -1)
            break;
        ReadCase();
    }
    return 0;
}

你可能感兴趣的:(最短路径)