zoukankan      html  css  js  c++  java
  • hdu 4885 (n^2*log(n)推断三点共线建图)+最短路

    题意:车从起点出发,每次仅仅能行驶L长度,必需加油到满,每次仅仅能去加油站或目的地方向,路过加油站就必需进去加油,问最小要路过几次加油站。

    開始时候直接建图,在范围内就有边1.跑最短了,再读题后发现,若几个点共线,且都在范围内,那么中间有点的俩头的点就不能有边,否则与条件相悖。关键是怎么用n^2*logn,的复杂度推断三点共线:点先按X排序,考察每一个点i时候,第二个点j,若直线ij斜率已经存在,则不能加入了,查找是否存在,用容器即可(mapset)都是logn的,所以满足要求。之后最短路即可。

    #include<iostream>
    #include<cstring>
    #include<queue>
    #include<cstdio>
    #include<algorithm>
    #include<map>
    using namespace std;
    const int inf=0x3f3f3f3f;
    struct points
    {
        long long x,y;
    };
    long long inline getdis(points a,points b)
    {
        return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
    }
    bool my(points a,points b)
    {
        if(a.x!=b.x)return a.x<b.x;
        else return a.y<b.y;
    }
    int n;long long l;
    points po[1005];
    int dis[1005][1008];
    int d[1005];int inq[1005];
    int ans=0;points s,t;int nums,numt;
    double inline getk(points a,points b)      //获得斜率
    {
        if(b.x==a.x)return inf;
        return  (a.y-b.y)*1.0/(a.x-b.x);
    }
    void spfa()
    {
        for(int i=0;i<n+2;i++)
        {
            d[i]=inf;
            inq[i]=0;
        }
        queue<int>q;
        inq[nums]=1;
        d[nums]=0;
        q.push(nums);
        while(!q.empty())
        {
            int cur=q.front();
            q.pop();
            inq[cur]=0;
            for(int i=0;i<n+2;i++)
            {
                if(d[i]>dis[cur][i]+d[cur])
                {
                   d[i]=dis[cur][i]+d[cur];
                   if(!inq[i])
                   {
                       q.push(i);
                       inq[i]=1;
                   }
                }
            }
        }
        return ;
    }
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d",&n,&l);
            scanf("%d%d",&po[0].x,&po[0].y);
            scanf("%d%d",&po[n+1].x,&po[n+1].y);
            s.x=po[0].x;    s.y=po[0].y;
            t.x=po[n+1].x;  t.y=po[n+1].y;
            for(int i=1;i<=n;i++)
                scanf("%d%d",&po[i].x,&po[i].y);
           sort(po,po+n+2,my);
           for(int i=0;i<=n+1;i++)               //起点,终点
            {
                if(po[i].x==s.x&&po[i].y==s.y)nums=i;
                if(po[i].x==t.x&&po[i].y==t.y)numt=i;
            }
             for(int i=0;i<=n+1;i++)
            {
                map<double,int>ma;
                for(int j=i+1;j<=n+1;j++)
                  {
                       if(getdis(po[i],po[j])<=l*l)        //在距离范围内的再查找。
                       {
                            double tempk=getk(po[i],po[j]);
                              if(ma.find(tempk)!=ma.end())
                                {
                                    dis[j][i]=dis[i][j]=inf;
                                }
                              else
                                 {
                                     dis[j][i]=dis[i][j]=1;
                                     ma[tempk]=1;
                                 }
                       }
                         else
                          dis[j][i]=dis[i][j]=inf;
                  }
            }
             spfa();
            if(d[numt]==inf)
               printf("impossible
    ");
            else
             printf("%d
    ",d[numt]-1);
        }
        return 0;
    }
    


  • 相关阅读:
    再次或多次格式化导致namenode的ClusterID和datanode的ClusterID之间不一致的问题解决办法
    Linux安装aria2
    POJ 3335 Rotating Scoreboard 半平面交
    hdu 1540 Tunnel Warfare 线段树 区间合并
    hdu 3397 Sequence operation 线段树 区间更新 区间合并
    hud 3308 LCIS 线段树 区间合并
    POJ 3667 Hotel 线段树 区间合并
    POJ 2528 Mayor's posters 贴海报 线段树 区间更新
    POJ 2299 Ultra-QuickSort 求逆序数 线段树或树状数组 离散化
    POJ 3468 A Simple Problem with Integers 线段树成段更新
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/4294170.html
Copyright © 2011-2022 走看看