POJ 1556 The Doors(判断线段相交 + 最短路)

RT。。题意和思路不是很复杂。。

没有注意 n = 0 的情况 WA 了几发。。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <utility>
#include <cmath>
using namespace std;

const int maxn = 20;
const double eps = 1e-4, inf = 1e10;

typedef struct point {
    double x;
    double y;
    int num;
}point;

typedef struct v {
    point start;
    point end;
}v;

double multi(point p1, point p2, point p0)  //used for Across
{
    return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y);
}

int Across(v v1, v v2)  //segmentCross,use functions: multi()
{
    if(max(v1.start.x,v1.end.x) >= min(v2.start.x, v2.end.x) &&
       max(v2.start.x,v2.end.x) >= min(v1.start.x, v1.end.x) &&
       max(v1.start.y,v1.end.y) >= min(v2.start.y, v2.end.y) &&
       multi(v2.start, v1.end, v1.start) * multi(v1.end, v2.end, v1.start) > 0 &&
       multi(v1.start, v2.end, v2.start) * multi(v2.end, v1.end, v2.start) > 0)
        return 1;
    else
        return 0;
}

point cham[maxn][6];
point p0, pe;

const int maxe = 20000, maxv = 200;

int fr[maxe], to[maxe];
double wt[maxe];
int head[maxv], next[maxe];
double sp[maxv];
int ecnt;

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

void adde(point a, point b)
{
    fr[ecnt] = to[ecnt + 1] = a.num;
    to[ecnt] = fr[ecnt + 1] = b.num;
    wt[ecnt] = wt[ecnt + 1] = dis(a, b);
    for(int i = ecnt; i < ecnt + 2; i++) {
        next[i] = head[fr[i]];
        head[fr[i]] = i;
    }
    ecnt += 2;
}

typedef pair<double, int> pii;
priority_queue <pii, vector<pii>, greater<pii> > que;
bool done[maxv];

double dijkstra()
{
    sp[p0.num] = 0;
    for(int i = 1; i <= pe.num; i++) sp[i] = inf;
    memset(done, false, sizeof(done));
    que.push(make_pair(sp[p0.num], p0.num));
    while(!que.empty()) {
        pii u = que.top(); que.pop();
        int cur = u.second;
        if(done[cur]) continue;
        done[cur] = true;
        for(int i = head[cur]; i != -1; i = next[i]) {
            int tar = to[i];
            if(sp[tar] > sp[cur] + wt[i]) {
                sp[tar] = sp[cur] + wt[i];
                que.push(make_pair(sp[tar], tar));
            }
        }
    }

    return sp[pe.num];
}

int main()
{
    int n;

    while(~scanf("%d", &n) && ~n) {
        if(n == 0) {
            printf("10.00\n");
            continue;
        }
        p0.x = 0;
        pe.x = 10;
        p0.y = pe.y = 5;
        p0.num = 0;
        pe.num = n * 6;
        v v0;
        v0.start = p0;
        v0.end = pe;
        bool ok1 = true;
        ecnt = 0;
        memset(head, -1, sizeof(head));
        for(int i = 0; i < n; i++)
            for(int j = 1; j < 5; j++)
                cham[i][j].num = i * 6 + j;
        for(int i = 0; i < n; i++) {
            scanf("%lf", &cham[i][0].x);
            cham[i][0].y = 0;
            for(int j = 1; j < 5; j++) {
                cham[i][j].x = cham[i][0].x;
                scanf("%lf", &cham[i][j].y);
                bool ok = true;
                v v1, v2;
                v1.start = p0;
                v1.end = cham[i][j];
                for(int k = 0; ok && k < i; k++) {
                    for(int p = 0; p < 5; p += 2) {
                        v2.start = cham[k][p];
                        v2.end = cham[k][p+1];
                        if(fabs(v2.start.x - v2.end.x) < eps && fabs(v2.start.y - v2.end.y) < eps)
                            continue;
                        if(Across(v1, v2)) {
                            ok = false;
                            break;
                        }
                    }
                }
                if(ok)
                    adde(p0, cham[i][j]);
                if(ok1 && j % 2 != 0) {
                    v2.start = cham[i][j-1];
                    v2.end = cham[i][j];
                    if(Across(v0, v2))
                        ok1 = false;
                }
            }
            cham[i][5].x = cham[i][0].x;
            cham[i][5].y = 10;
        }
        if(ok1)
            adde(p0, pe);
        for(int i = 0; i < n; i++) {
            for(int it = 1; it < 5; it++) {
                v v1, v2;
                v1.start = cham[i][it];
                for(int j = i+1; j < n; j++) {
                    for(int jt = 1; jt < 5; jt++) {
                        v1.end = cham[j][jt];
                        bool ok = true;
                        for(int k = i+1; ok && k < j; k++) {
                            for(int kt = 0; kt < 5; kt += 2) {
                                v2.start = cham[k][kt];
                                v2.end = cham[k][kt+1];
                                if(Across(v1, v2)) {
                                    ok = false;
                                    break;
                                }
                            }
                        }
                        if(ok)
                            adde(cham[i][it], cham[j][jt]);
                    }
                }
                v1.end = pe;
                bool oke = true;
                for(int j = i+1; oke && j < n; j++) {
                    for(int jt = 0; jt < 5; jt += 2) {
                        v2.start = cham[j][jt];
                        v2.end = cham[j][jt+1];
                        if(Across(v1, v2)) {
                            oke = false;
                            break;
                        }
                    }
                }
                if(oke)
                    adde(cham[i][it], pe);
            }
        }
        printf("%.2lf\n", dijkstra());
    }

    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值