zoukankan      html  css  js  c++  java
  • Treasure Hunt--poj1066(最短路加判断线段的关系)

    http://poj.org/problem?id=1066

    题目大意:有n条线段 他们都在这个房间里   最后有一个点代表起始位置

    现在想通过墙出去  他只能爆破每个房间的中点的门   问最少的门通过的

    分析:   刚开始就想到暴力写   但是一想好麻烦   头都大了   最后还是暴力   我把边存错了 调试了好久  就过了

    先找到每条线段(包括边界)与所有的线段之间的交点求出来   然后从左往右排下序  把中点存到一个结构体里(把边界的点特殊处理一下)

    处理所有的中点   能直接相连的就置成1  否则就是INF     最后地杰斯特拉跑一边   把边缘的点比较一下就好

    用G++ 交   c++的话  就把fabs改成abs就好  反正它本身就是整形

    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    #include<ctype.h>
    #include<math.h>
    #include<queue>
    #include<algorithm>
    #include<iostream>
    
    using namespace std;
    #define N 2000
    const double ESP = 1e-8;
    #define INF 0x3f3f3f3f
    #define memset(a,b) memset(a,b,sizeof(a))
    
    int n;
    
    struct Point
    {
        double x,y;
        int step;
        Point (double x=0,double y=0):x(x),y(y) {}
    
        Point operator - (const Point &temp)const
        {
            return Point(x-temp.x,y-temp.y);
        }
        int operator * (const Point &temp)const
        {
            double t=(x*temp.y-y*temp.x);
            if(t>ESP)
                return 1;
            if(fabs(t)<ESP)
                return 0;
            return -1;
        }
    };
    
    struct node
    {
        Point A,B;
        node (Point A=0,Point B=0):A(A),B(B) {}
    
    };
    
    Point p[N],d[N];
    node a[N];
    
    Point line(Point u1,Point u2,Point v1,Point v2)///求交点
    {
        Point ret=u1;
        double t=((u1.x-v1.x)*(v1.y-v2.y)-(u1.y-v1.y)*(v1.x-v2.x))/((u1.x-u2.x)*(v1.y-v2.y)-(u1.y-u2.y)*(v1.x-v2.x));
    
        ret.x+=(u2.x-u1.x)*t;
        ret.y+=(u2.y-u1.y)*t;
    
        return ret;
    }
    
    int cmp(const void *aa,const void *bb)
    {
        struct Point *cc,*dd;
        cc=(struct Point *)aa;
        dd=(struct Point *)bb;
        if(cc->x!=dd->x)
            return cc->x-dd->x;
        else
            return cc->y-dd->y;
    }
    
    
    int G[N][N];
    
    void serch(int o)
    {
        for(int i=0;i<=o;i++)
        {
            for(int j=0;j<=o;j++)
            {
                if(i==j)
                    continue;
                int flag=0;
                for(int k=1;k<n;k++)
                {
                    int k1=fabs((d[i]-a[k].A)*(a[k].B-a[k].A)+(d[j]-a[k].A)*(a[k].B-a[k].A));
                    int k2=fabs((a[k].A-d[j])*(d[i]-d[j])+(a[k].B-d[j])*(d[i]-d[j]));
                    if(k1==0 && k2==0)
                    {
                        flag=1;
                        break;
                    }
                }
                if(flag==0)
                    G[i][j]=1;
            }
        }
    }
    
    int vis[N],dis[N];
    
    void dji(int s,int o)
    {
        memset(vis,0);
        for(int i=0;i<=o;i++)
            dis[i]=G[s][i];
        for(int i=0;i<=o;i++)
        {
            int Min=INF,dist;
            for(int j=0;j<=o;j++)
            {
                if(!vis[j] && Min>dis[j])
                {
                    Min=dis[j];
                    dist=j;
                }
            }
            vis[dist]=1;
            for(int j=0;j<=o;j++)
            {
                dis[j]=min(dis[j],dis[dist]+G[dist][j]);
            }
        }
    }
    
    int main()
    {
    
        double x1,x2,y1,y2;
        while(scanf("%d",&n)!=EOF)
        {
    
            double x,y;
            for(int i=1; i<=n; i++)
            {
                scanf("%lf %lf %lf %lf",&x1,&y1,&x2,&y2);
                a[i]=node(Point(x1,y1),Point(x2,y2));
            }
            n=n+1;
            a[n++]=node(Point(0,0),Point(0,100));
            a[n++]=node(Point(0,0),Point(100,0));
            a[n++]=node(Point(0,100),Point(100,100));
            a[n++]=node(Point(100,0),Point(100,100));
    
            scanf("%lf %lf",&x,&y);
            int o=0;///中点的个数
            int h[N];///在边缘的点
            int aa=0;///边缘点的个数
            for(int i=1; i<n; i++)
            {
                memset(p,0);
                int b=0;
                for(int j=1; j<n; j++)
                {
                    if(i==j)
                        continue;
                    int k=fabs((a[i].B-a[j].A)*(a[j].B-a[j].A)+(a[i].A-a[j].A)*(a[j].B-a[j].A));
                    int kk=fabs((a[j].B-a[i].A)*(a[i].B-a[i].A)+(a[j].A-a[i].A)*(a[i].B-a[i].A));
                    if(k!=2 && kk!=2)///如果两个线段相交 求交点
                    {
                        p[b++]=line(a[i].A,a[i].B,a[j].A,a[j].B);
                    }
                }
                qsort(p,b,sizeof(p[0]),cmp);///交点从左向右排序
    
                for(int j=1;j<b;j++)///每一条线段的中点
                {
                    d[o]=Point((p[j].x+p[j-1].x)/2.0,(p[j].y+p[j-1].y)/2.0);
                    if(d[o].x==0 || d[o].x==100 || d[o].y==0 || d[o].y==100)///边界点
                    {
                        h[aa++]=o;
                    }
                    o++;
                }
            }
            d[o]=Point(x,y);///起始点
            for(int i=0;i<=o;i++)
            {
                for(int j=0;j<=o;j++)
                    G[i][j]=INF;
            }
            serch(o);///判断这两个中点是否能直接相连
            dji(o,o);///最短路
            int Min=INF;
            for(int i=0;i<aa;i++)
            {
                Min=min(Min,dis[h[i]]);
            }
            printf("Number of doors = %d 
    ",Min);
        }
        return 0;
    }
  • 相关阅读:
    【洛谷】3966:[TJOI2013]单词【AC自动机】【fail树】
    CF980E The Number Games【树链剖分/线段树】
    【扫描线模板】
    【洛谷】3402:【模板】可持久化并查集
    【洛谷】1525:关押罪犯【并查集】【二分+二分图判断】
    【洛谷】4180:【模板】严格次小生成树[BJWC2010]【链剖】【线段树维护最大、严格次大值】
    【POJ】2796:Feel Good【单调栈】
    【POJ】1862:Stripies【贪心】【优先队列】
    《中间人攻击——wikipedia》——学习摘要
    《中间人攻击——ARP欺骗的原理、实战及防御》——学习摘要
  • 原文地址:https://www.cnblogs.com/linliu/p/5434658.html
Copyright © 2011-2022 走看看