Poj 1556 The Doors

来源:互联网 发布:最新抢火车票软件 编辑:程序博客网 时间:2024/05/16 09:47
题意:
求穿越对角线为(0,0,10,10)矩形的(0,5)到(10,5)的最短路径


        在矩形里面存在竖直的墙体, 没个墙上在上面开了两个口:用5个参数描述x,y1, y2, y3, y4
x为墙的x坐标,y1-y4为从下到上的缺口端点


方法: 以所有墙的墙角(缺口处)和起始两点为顶点,建立无向图。
建图过程中需要判断两条线段是否相交。


=》知识点:最短路 + 线段相交判定。 最短路用Dijkstar即可


判断线段相交: 利用叉积(相乘大于零逆时针)
1.如果Line1的两个顶点在Line2的同侧,则不相交
2.若1不成立,判断Line2的两个顶点在Line1的同侧,则不想交

3.若2不成立,则线段相交


#include <cstdio>#include <cstring>#include <string>#include <string>#include <cmath>#include <algorithm>#include <vector>#include <queue>#define MAX 10005#define INF 100000000#define PI acos(-1.0)#include <iostream>using namespace std;//0ms 1Ystruct Vector2d{    double x, y;    Vector2d(){}    Vector2d(double xx, double yy){ x =  xx; y = yy;}    Vector2d(const Vector2d &v){x = v.x; y = v.y;};    double crossMul(const Vector2d &vec)const{        //Vector2d ans((x * vec.y), (y * vec.x));        return (x * vec.y) -  (y * vec.x);    }    Vector2d sub(const Vector2d &point)const{        Vector2d ans(x - point.x, y - point.y);        return ans;    }    double getLength()const{        return sqrt(x * x + y * y);    }    void output(){        cout<<x<<" "<<y<<endl;    }};struct Line{    Vector2d p1;    Vector2d p2;    Line(){}    Line(const Vector2d &mp1, const Vector2d &mp2):p1(mp1), p2(mp2){}    bool isInsect(const Line &line)const{        Vector2d va = line.p1.sub(p1), vb = line.p1.sub(p2);        double cmRes1 = va.crossMul(vb);        va = line.p2.sub(p1); vb  = line.p2.sub(p2);        double cmRes2 = va.crossMul(vb);        if(cmRes1 == 0 || cmRes2 == 0)return true;        if( (cmRes1 > 0 && cmRes2 > 0) || (cmRes1 < 0 && cmRes2 < 0) )///同号不想交            return false;        va = p1.sub(line.p1); vb = p1.sub(line.p2 );        cmRes1 = va.crossMul(vb);        va = p2.sub(line.p1); vb = p2.sub(line.p2);        cmRes2 = va.crossMul(vb);        if(cmRes1 == 0 || cmRes2 == 0)return true;         if( (cmRes1 > 0 && cmRes2 > 0) || (cmRes1 < 0 && cmRes2 < 0) )///同号不相交            return false;        return true;    }    double getLength(){        return p1.sub(p2).getLength();    }};struct Wall{    double x, y1, y2, y3, y4;    void input(){        cin>>x>>y1>>y2>>y3>>y4;    }    Vector2d getPoint(int index)const{        Vector2d vec;        vec.x = x;        switch(index){            case 1:                vec.y = y1;break;            case 2:                vec.y = y2; break;            case 3:                vec.y = y3; break;            case 4:                vec.y = y4; break;            default:                puts("index outof bounds");                break;        }        return vec;    }}walls[MAX];struct Edge{    int pos, next;    double val;}edge[MAX * 2];int N, vN;int head[MAX], e;Vector2d start(0, 5);Vector2d end(10, 5);bool isCanLink(const int &ii, const int &i, Vector2d &pNow , Vector2d &pTest);void insert(int a, int b,  double val){    edge[e].next = head[a];    edge[e].pos = b;    edge[e].val = val;    head[a] = e++;}void showMap(){    for(int i = 0;  i < vN; i++){        int next = head[i], pos;        printf("head : %d\n", i);        while(next != -1){            pos = edge[next].pos;            cout<<pos<<"->"<<edge[next].val<<":::";            next = edge[next].next;        }cout<<endl;    }}void init(){    e = 0;    memset(head, -1, sizeof(head));    vN = N * 4 + 2;//0 - (vN - 1)    for(int i = 0; i < N; i++){            walls[i].input();    }//end input}void makeMap(){//O(vN^2)    Vector2d pNow, pTest;    Line line;    for(int i= 0;i < N; i++){        for(int j = 1; j <= 4; j++ ){            pNow = walls[i].getPoint(j);//            puts("pNow get");            for(int ii  = i - 1; ii >= 0; ii--){                for(int jj = 1; jj <= 4; jj++){                    pTest = walls[ii].getPoint(jj);//                    puts("pTest get");                    if(isCanLink(ii, i, pNow, pTest)){                        int a = i * 4 + j, b = ii * 4 + jj;                        line.p1 = pNow;                        line.p2 = pTest;                        double val = line.getLength();                        insert(a, b, val);                        insert(b, a, val);                    }                }            }//之前检测完毕            line.p1 = pNow;            line.p2 = start;            if(isCanLink(-1, i, pNow, start)){                int a = i * 4 + j, b = 0;                double val = line.getLength();                insert(a, b, val);                insert(b, a, val);            }         }    }//全部线段之前检测完毕//      puts("end point left");      pNow = end;      for(int ii  = N - 1; ii >= 0; ii--){                for(int jj = 1; jj <= 4; jj++){                    pTest = walls[ii].getPoint(jj);                    if(isCanLink(ii, N, pNow, pTest)){                        int a = ii * 4 + jj, b = vN - 1;                        line.p1  = pNow;                        line.p2 =  pTest;                        double val = line.getLength();                        insert(a, b, val);                        insert(b, a, val);                    }                }      }//最后之前一点检测完毕      if(isCanLink(-1, N, start, end)){            int a = 0, b = vN - 1;            double val = start.sub(end).getLength();            insert(a, b, val);            insert(b, a, val);      }//全部点处理完毕}bool isCanLink(const int &ii, const int &i, Vector2d &pNow , Vector2d &pTest){    Line line1(pNow, pTest), line2;//    puts("judge : ");//    pNow.output();pTest.output();    for(int ptr = i  - 1; ptr > ii ; ptr --){        int canPass = 2;        for(int j = 1; j <= 4; j+= 2){            line2.p1 = walls[ptr].getPoint(j);            line2.p2 = walls[ptr].getPoint(j + 1);            if(!line1.isInsect(line2)){//不过缺口线段则不可连接                canPass --;//                printf("cannot Insect at %d: %d with lines\n", ptr, j);//                line1.p1.output();line1.p2.output();//                line2.p1.output();line2.p2.output();//                puts("end");            }        }        if(canPass == 0){            return false;        }    }//    puts("can link");    return true;}void dijkstra(){    double d[MAX];    bool v[MAX];    for(int i = 0; i < vN; i++){        d[i] = INF; v[i] = false;    }    d[0] = 0;    double min_d;    int index;    for(int i  = 0; i < vN - 1; i++){        min_d = INF; index = -1;        for(int j = 0; j < vN; j++){            if(!v[j] && min_d > d[j]){                min_d = d[j];                index = j;            }        }        if(index != -1){            v[index] = true;            int next = head[index], pos;            while(next != -1){                pos = edge[next].pos;                if(!v[pos]){                    double dist = d[index] + edge[next].val;                    if(d[pos] > dist)d[pos] = dist;                }                next = edge[next].next;            }        }    }    printf("%.2f\n", d[vN -1]);}int main(){    while(cin>>N, N != -1){        init();//        puts("init end");        makeMap();//        showMap();//        puts("makeMap end");        dijkstra();    }    return 0;}


原创粉丝点击