我是靠谱客的博主 机智饼干,最近开发中收集的这篇文章主要介绍【图论】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.00n");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("%.2lfn",k);
    }   
}

 

 

 

 

 

 

最后

以上就是机智饼干为你收集整理的【图论】Car的旅行线路 NOIP 2001的全部内容,希望文章能够帮你解决【图论】Car的旅行线路 NOIP 2001所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(44)

评论列表共有 0 条评论

立即
投稿
返回
顶部