洛谷P1027 [NOIP2001 提高组] Car 的旅行路线(计算几何+最短路)

题目链接
题目大意:给你s个城市,每个城市有四个机场,每个城市内机场两两之间有直达路径,所有城市内两两之间的机场都有可直达路径,问从a到b城市最短的路径是多少,出发点和结束点机场任选。
分析:思路大致就是对所有点建边,然后folyed或者四次单源最短路更新答案即可,关键点是建图。
然后问题关键要解决的就是矩形的第四个点怎么求,我们可以利用勾股定理,求出给定三点见两两之间的距离,然后判断哪条边是直角边,最后直接计算坐标即可。(具体看代码)

#include<bits/stdc++.h>
#define MAIN main
using namespace std;
typedef long long ll;
const double eps=1e-8;
const double pi=acos(-1.0);
const int inf=0x3f3f3f3f;
const int N=1e5+10;
int n,s,a,b;
double t;
int sgn(double x)
{
    
    
    if(fabs(x)<eps) return 0;
    return x>0?1:-1;
}
struct Point
{
    
    
    double x,y;
    int num;
    Point (double x=0,double y=0,int num=0):x(x),y(y),num(num){
    
    }
    bool operator != (Point a){
    
    
        return sgn(x-a.x)!=0&&sgn(y-a.y)!=0;
    }
};
struct edge
{
    
    
    int v,next;
    double w;
}e[N<<1];
int head[N],cnt;
void add(int u,int v,double w)
{
    
    
    e[++cnt].v=v;
    e[cnt].w=w;
    e[cnt].next=head[u];
    head[u]=cnt;
    e[++cnt].v=u;
    e[cnt].w=w;
    e[cnt].next=head[v];
    head[v]=cnt;
}
double Distance(Point a,Point b)
{
    
    
    double d1=a.x-b.x;
    double d2=a.y-b.y;
    return sqrt(d1*d1+d2*d2);
}
struct node
{
    
    
    Point p[4];
    node(){
    
    }
    void build(double T)
    {
    
    
        for(int i=0;i<=3;i++){
    
    
            for(int j=i+1;j<=3;j++){
    
    
                add(p[i].num,p[j].num,T*Distance(p[i],p[j]));
            }
        }
    }
};
node c[N];
void Add(node u,node v)
{
    
    
    add(u.p[0].num,v.p[0].num,t*Distance(u.p[0],v.p[0]));
    add(u.p[0].num,v.p[1].num,t*Distance(u.p[0],v.p[1]));
    add(u.p[0].num,v.p[2].num,t*Distance(u.p[0],v.p[2]));
    add(u.p[0].num,v.p[3].num,t*Distance(u.p[0],v.p[3]));
    add(u.p[1].num,v.p[0].num,t*Distance(u.p[1],v.p[0]));
    add(u.p[1].num,v.p[1].num,t*Distance(u.p[1],v.p[1]));
    add(u.p[1].num,v.p[2].num,t*Distance(u.p[1],v.p[2]));
    add(u.p[1].num,v.p[3].num,t*Distance(u.p[1],v.p[3]));
    add(u.p[2].num,v.p[0].num,t*Distance(u.p[2],v.p[0]));
    add(u.p[2].num,v.p[1].num,t*Distance(u.p[2],v.p[1]));
    add(u.p[2].num,v.p[2].num,t*Distance(u.p[2],v.p[2]));
    add(u.p[2].num,v.p[3].num,t*Distance(u.p[2],v.p[3]));
    add(u.p[3].num,v.p[0].num,t*Distance(u.p[3],v.p[0]));
    add(u.p[3].num,v.p[1].num,t*Distance(u.p[3],v.p[1]));
    add(u.p[3].num,v.p[2].num,t*Distance(u.p[3],v.p[2]));
    add(u.p[3].num,v.p[3].num,t*Distance(u.p[3],v.p[3]));
}
double dis[N];
int vis[N];
double ans;
void dijkstra(int ss)
{
    
    
    priority_queue<pair<double,int> >q;
    for(int i=1;i<=s*4;i++) vis[i]=0,dis[i]=1e10;
    dis[ss]=0;
    q.push(make_pair(-dis[ss],ss));
    while(!q.empty())
    {
    
    
        int u=q.top().second;
        q.pop();
        if(vis[u]) continue;
        vis[u]=1;
        for(int i=head[u];i;i=e[i].next)
        {
    
    
            int v=e[i].v;
            if(dis[v]>dis[u]+e[i].w)
            {
    
    
                dis[v]=dis[u]+e[i].w;
                q.push(make_pair(-dis[v],v));
            }
        }
    }
    ans=min(ans,dis[c[b].p[0].num]);
    ans=min(ans,dis[c[b].p[1].num]);
    ans=min(ans,dis[c[b].p[2].num]);
    ans=min(ans,dis[c[b].p[3].num]);
}
int MAIN()
{
    
    
    scanf("%d",&n);
    while(n--)
    {
    
    
        scanf("%d%lf%d%d",&s,&t,&a,&b);
        int num=0;
        cnt=0;
        memset(head,0,sizeof(head));
        for(int i=1;i<=s;i++){
    
    
            int x1,y1,x2,y2,x3,y3,T;
            scanf("%d%d%d%d%d%d%d",&x1,&y1,&x2,&y2,&x3,&y3,&T);
            int x4,y4;
            double ab=(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
            double ac=(x1-x3)*(x1-x3)+(y1-y3)*(y1-y3);
            double bc=(x2-x3)*(x2-x3)+(y2-y3)*(y2-y3);
            if(ab+ac==bc) x4=x2+x3-x1,y4=y2+y3-y1;
            if(ab+bc==ac) x4=x1+x3-x2,y4=y1+y3-y2;
            if(ac+bc==ab) x4=x1+x2-x3,y4=y1+y2-y3;
            c[i].p[0]=Point(x1,y1,++num);
            c[i].p[1]=Point(x2,y2,++num);
            c[i].p[2]=Point(x3,y3,++num);
            c[i].p[3]=Point(x4,y4,++num);
            c[i].build(T);
        }
        for(int i=1;i<=s;i++){
    
    
            for(int j=i+1;j<=s;j++){
    
    
                Add(c[i],c[j]);
            }
        }
        ans=1e20;
        for(int i=0;i<=3;i++) dijkstra(c[a].p[i].num);
        printf("%.1f\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/amazingee/article/details/113526022