• 【图论】Car的旅行线路 NOIP 2001


    【NOIP2001】Car的旅行线路

    题目描述

    又到暑假了,住在城市A的Car想和朋友一起去城市B旅游。 她知道每个城市都有四个飞机场,分别位于一个矩形的四个顶点上,同一个城市中两个机场之间有一条笔直的高速铁路,第I个城市中高速铁路了的单位里程价格为Ti,任意两个不同城市的机场之间均有航线,所有航线单位里程的价格均为t。 那么Car应如何安排到城市B的路线才能尽可能的节省花费呢?她发现这并不是一个简单的问题,于是她来向你请教。 任务: 找出一条从城市A到B的旅游路线,出发和到达城市中的机场可以任意选取,要求总的花费最少。

    输入

    第一行为一个正整数n(1≤n≤10),表示有n组测试数据。

    每组的第一行有四个正整数s,t,A,B。 S(0<S≤100)表示城市的个数,t表示飞机单位里程的价格,A,B分别为城市A,B的序号,(1≤A,B≤S)。

    接下来有S行,其中第I行均有7个正整数xi1,yi1,xi2,yi2,xi3,yi3,Ti,这当中的(xi1,yi1),(xi2,yi2),(xi3,yi3)分别是第I个城市中任意三个机场的坐标,TI为第I个城市高速铁路单位里程的价格。

    输出

    共有n行,每行一个数据对应测试数据,结果保留2位小数。

    样例输入

    1
    3 10 1 3
    1 1 1 3 3 1 30
    2 5 7 4 5 2 1
    8 6 8 8 11 6 3

    样例输出

    47.55

    最开始,让我烧脑的就是怎么求第4个机场的坐标。后来发现,在一个平面直角坐标系的矩形中,一个顶点的坐标就是两个相邻点的坐标之和减去对点的坐标。举一个例子:

    A(1,2),B(2,4),C(3,1),那么D点就是(B的坐标+C的坐标-A的坐标):

    XD=2+3-1=4;YD=4+1-2=3;∴D(4,3)。

    可是要这样的话我们必须还要判断3个点中哪两个点是第4个点的相邻点。我们先在刚才那个矩形中不看D点,然后把A,B,C连成一个Rt△,发现A点就是直角顶点,而我们在刚才计算过程中所减去的对角就是A,所以得出一个结论:

    三个点中的直角顶点就是需要减去的那个对点。

    所以再初始化每个机场之间的距离,用两点间距离公式——

    A(x1,y1),B(x2,y2)之间AB=√(x1-x2)²+(y1-y2)²

    然后再把每个距离来乘飞机的单价或高速铁路的单价。这里要注意一个判断两机场是否在同一城市时。不能用

    if(i/4==j/4) dis[i][j]*=lufei[i/4];

    因为比如i为3、j为4时,i/4≠j/4。所以要用

    if((i-1)/4==(j-1)/4) dis[i][j]*=lufei[(i-1)/4+1];

    这样就不会判断错误了。

    最后再用Floyed(随便,根据自己喜好)来搜就行了。

    代码如下:

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<iostream>
    using namespace std;
    int t,s,p,A,B,x,xx,xxx,y,yy,yyy,xd,yd,m,n,xxxx[401],yyyy[401],lu[101];
    double dis[401][401];
    void Z(int xa ,int xb ,int xc ,int ya ,int yb ,int yc)
    {
        double ab=(xa-xb)*(xa-xb)+(ya-yb)*(ya-yb);
        double ac=(xa-xc)*(xa-xc)+(ya-yc)*(ya-yc);
        double bc=(xb-xc)*(xb-xc)+(yb-yc)*(yb-yc);
        if(ab+ac==bc)//bc为斜边,A为对角
        {
            xd=xb+xc-xa;
            yd=yb+yc-ya;
            return ;
        }
             
        if(ab+bc==ac)//ac为斜边,B为对角
        {
            xd=xa+xc-xb;
            yd=ya+yc-yb;
            return ;
        }
         
        if(ac+bc==ab)//ab为斜边,C为对角
        {
            xd=xa+xb-xc;
            yd=ya+yb-yc;
            return ;
        }
         
    }
     
    void Dis()
    {
        for(int i=n+1;i<=n+4;i++) dis[i][i]=0;//先更新同一个城市的距离
        dis[n+1][n+2]=dis[n+2][n+1]=sqrt((x-xx)*(x-xx)+(y-yy)*(y-yy));
        dis[n+1][n+3]=dis[n+3][n+1]=sqrt((x-xxx)*(x-xxx)+(y-yyy)*(y-yyy));
        dis[n+1][n+4]=dis[n+4][n+1]=sqrt((x-xd)*(x-xd)+(y-yd)*(y-yd));
        dis[n+2][n+3]=dis[n+3][n+2]=sqrt((xx-xxx)*(xx-xxx)+(yy-yyy)*(yy-yyy));
        dis[n+2][n+4]=dis[n+4][n+2]=sqrt((xx-xd)*(xx-xd)+(yy-yd)*(yy-yd));
        dis[n+3][n+4]=dis[n+4][n+3]=sqrt((xxx-xd)*(xxx-xd)+(yyy-yd)*(yyy-yd));
    }
     
    void Y()
    {
        for(int u=1;u<=s*4;u++)
        {
            for(int v=1;v<=s*4;v++)
            {
                if((u-1)/4==(v-1)/4)//同一个城市
                    dis[u][v]*=lu[(u-1)/4+1];
                else//不同城市
                {
                    dis[u][v]=sqrt((xxxx[u]-xxxx[v])*(xxxx[u]-xxxx[v])+(yyyy[u]-yyyy[v])*(yyyy[u]-yyyy[v]))*p;
                }
            }
        }
    }
     
    int main()
    {
        scanf("%d",&t);
        while(t--)
        {
            memset(dis,0x7f,sizeof(dis));
            memset(xxxx,0,sizeof(xxxx));
            memset(yyyy,0,sizeof(yyyy));
            memset(lu,0,sizeof(lu));    
            n=0;
            scanf("%d%d%d%d",&s,&p,&A,&B);
            if(A==B){printf("0.00
    ");continue;}
            for(int ll=1;ll<=s;ll++)
            {
                scanf("%d %d %d %d %d %d %d",&x,&y,&xx,&yy,&xxx,&yyy,&m);lu[ll]=m;
                Z(x,xx,xxx,y,yy,yyy);
                Dis();
                xxxx[++n]=x;yyyy[n]=y;//存点坐标
                xxxx[++n]=xx;yyyy[n]=yy;
                xxxx[++n]=xxx;yyyy[n]=yyy;
                xxxx[++n]=xd;yyyy[n]=yd;
            }
            Y();
            for(int k=1;k<=s*4;k++)//Floyed
                for(int i=1;i<=s*4;i++)
                    for(int j=1;j<=s*4;j++)
                        dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
            double k=1<<30;
            for(int i=1;i<=4;i++)//两个城市的每个机场到每个机场的距离找最小的
                for(int j=1;j<=4;j++)
                    k=min(k,dis[(A-1)*4+i][(B-1)*4+j]);
            printf("%.2lf
    ",k);
        }   
    }
  • 相关阅读:
    使用C#调用系统API实现锁定计算机
    阶段性总结
    心情状态所困
    VMware虚拟机网络配置相关备忘
    数据库学习第一篇
    给window xp sp2设置共享文件夹
    转报竞赛实操试题
    数据库视频笔记
    Android开发从零开始,搭建交叉编译环境
    排故总结
  • 原文地址:https://www.cnblogs.com/Orz-IE/p/12039533.html
Copyright © 2020-2023  润新知