蓝桥杯 算法训练 Car的旅行路线(Floyd算法)

问题描述
  又到暑假了,住在城市A的Car想和朋友一起去城市B旅游。她知道每个城市都有四个飞机场,分别位于一个矩形的四个顶点上,同一个城市中两个机场之间有一 条笔直的高速铁路,第I个城市中高速铁路了的单位里程价格为Ti,任意两个不同城市的机场之间均有航线,所有航线单位里程的价格均为t。
  那么Car应如何安排到城市B的路线才能尽可能的节省花费呢?她发现这并不是一个简单的问题,于是她来向你请教。
  找出一条从城市A到B的旅游路线,出发和到达城市中的机场可以任意选取,要求总的花费最少。
输入格式
  输入的第一行有四个正整数s,t,A,B。
  S表示城市的个数,t表示飞机单位里程的价格,A,B分别为城市A,B的序号,(1<=A,B<=S)。
  接下来有S行,每行均有7个正整数xi1,yi1,xi2,yi2,xi3,yi3,Ti,这当中的(xi1,yi1),(xi2,yi2),(xi3,yi3)分别是第I个城市中任意三个机场的坐标,T I为第I个城市高速铁路单位里程的价格。
输出格式
  输出最少的花费,保留一位小数。
样例输入
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
数据规模和约定
  0<S<=100


其实这道题不是很难,把各个机场编号,就能建立无向图G【i】【j】表示各个机场之间通行的花费,然后用Floyd算法求出最短路即可。有一个难点在于利用矩形条件求各个城市最后一个机场坐标,我们利用矩形两组不相邻的顶点坐标之和相等来求。具体解析见代码:

#include<cstdio>
#include<algorithm>
#include<queue>
#include<iostream>
#include<cstring>
#include<cmath>
#define Inf 99999999
using namespace std;
struct City
{
    float x[4];
    float y[4];
    float cost;
}city[100];
void Seek(struct City c,float &x3,float &y3)
{
    if((c.x[0]-c.x[1])*(c.x[2]-c.x[1])+(c.y[0]-c.y[1])*(c.y[2]-c.y[1])==0) //直角点是(x[1],y[1])
        {swap(c.x[0],c.x[1]);swap(c.y[0],c.y[1]);}
    else if((c.x[0]-c.x[2])*(c.x[1]-c.x[2])+(c.y[0]-c.y[2])*(c.y[1]-c.y[2])==0)//直角点是(x[2],y[2])
        {swap(c.x[0],c.x[2]);swap(c.y[0],c.y[2]);}
    x3=c.x[1]+c.x[2]-c.x[0];
    y3=c.y[1]+c.y[2]-c.y[0];
}
float dis(struct City a,int index1,struct City b,int index2)
{
    return sqrt((a.x[index1]-b.x[index2])*(a.x[index1]-b.x[index2])+(a.y[index1]-b.y[index2])*(a.y[index1]-b.y[index2]));
}
int main()
{
    float G[405][405];
    int s,t,a,b;
    cin>>s>>t>>a>>b;
    for(int i=0; i<s; i++)
    {
       for(int u=0;u<3;u++)
       {
           cin>>city[i].x[u]>>city[i].y[u];
       }
       cin>>city[i].cost;
       float x3,y3;
       Seek(city[i],x3,y3);
       city[i].x[3]=x3;
       city[i].y[3]=y3;
    }
    for(int i=0; i<4*s; i++)
        for(int j=0; j<4*s; j++)
        {
            if(i==j)
                G[i][j]=0;
            else if(i/4==j/4)
                G[i][j]=dis(city[i/4],i%4,city[j/4],j%4)*city[i/4].cost;
            else
                G[i][j]=dis(city[i/4],i%4,city[j/4],j%4)*t;
        }
for(int k=0; k<4*s; k++)
    for(int i=0; i<4*s; i++)
        for(int j=0; j<4*s; j++)
            {
                G[i][j]=min(G[i][j],G[i][k]+G[k][j]);
            }
    float mindis=Inf;
    for(int i=4*a-4; i<4*a; i++)
        for(int j=4*b-4; j<4*b; j++)
        {
            mindis=min(mindis,G[i][j]);
        }
    printf("%.1f\n",mindis);
    return 0;
}

其实这道题博主写了两个小时,本来三十分钟就能ac的题emmm,原因是之前好像是听哪个老师还是算法书上说,floyd算法k放在最外层或者最内层都行。。。。然后今天一查才知道,k只能放在最外层!!!看了知乎上大手子的讲解,算是明白为什么了。在动态规划算法进行到k时,必须保证k-1时的状态完全得到更新。

附上知乎大手子的讲解:


猜你喜欢

转载自blog.csdn.net/langzitan123/article/details/80213847