洛谷1027 car的旅行路线

本博客主要探讨NOIP 2001 T4题目,即洛谷1027 - Car的旅行路线。通过最短路算法Floyd解决稠密图的路径问题,涉及计算几何和数据转换。文章强调了初始化数组和理解数据读入格式的重要性,并提供了参考代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

NOIP 2001 T4

原题地址:

https://www.luogu.org/problem/show?pid=1027

最短路Floyd 计算几何

解题思路

说白了就是一个稠密图的最短路问题,图稠密到每两个点之间都有连边,所以跑floyd又安全又好打,虽然数据太水spfa啥的也能跑过,但毕竟题目给的数据范围还是挺吓人的,最好别以身试毒冒险。然而这个题的关键不在于最短路怎么打,而是初始化,再往前延伸就是这巨坑无比的数据读入格式怎么转化成有效信息……

Point.1 坐标存储

是的,这个题的数据读入简直是简直了……给出矩形的三个顶点坐标求剩下那个的坐标,数学渣表示一脸懵逼……于是参考了cgk大神的blog,瞬间觉得被耍了……

http://chenguokai.16mb.com/%e7%ae%97%e6%b3%95%e5%a5%a5%e8%b5%9b%e9%a2%98%e7%9b%ae/%e6%b4%9b%e8%b0%b7-p1027-car%e7%9a%84%e6%97%85%e8%a1%8c%e8%b7%af%e7%ba%bf-%e8%a7%a3%e9%a2%98%e6%8a%a5%e5%91%8a/

Point.2 数组初始化

说是整道题最核心的部分也不为过(当然如果point.1解决不了剩下的都是浮云)。总之就是一个城市有四个点,两两连边,边权为距离*车费;分属不同城市的点两两连边,边权为距离*飞机票钱。

Point.3 floyd

最简单的最短路算法,三重循环O(n^3)。数据太水(只有5个点而且远没有到题干上给出的数据范围那么大,所以这种其实时间复杂度很高的算法也不会T)

参考代码(有点复杂凑合着看吧)

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
using namespace std;
 
int x[15][5],y[15][5],t[105];
double dist[500][500];
struct mc1
{
     int x,y;
}e[500];
struct mc2
{
     int pos[5];
}q[105];
 
double dis(int x1,int y1,int x2,int y2)
{
     returnsqrt((double)((x2-x1)*(x2-x1))+(double)((y2-y1)*(y2-y1)));
}
 
double max_(double x,double y,double z)
{
     double re=x;
     if (y>re) re=y;
     if (z>re) re=z;
     return re;
}
 
int main()
{
     int n;
     cin>>n;
     int s,p,a,b;
     cin>>s>>p>>a>>b;
     int cnt=0;
     for (inti=1;i<=s;i++)
     {
         cin>>x[i][1]>>y[i][1]>>x[i][2]>>y[i][2]>>x[i][3]>>y[i][3]>>t[i];
         doublep1=dis(x[i][1],y[i][1],x[i][2],y[i][2]);
         doublep2=dis(x[i][1],y[i][1],x[i][3],y[i][3]);
         doublep3=dis(x[i][2],y[i][2],x[i][3],y[i][3]);
         double mx=max_(p1,p2,p3);//求第四个顶点的坐标;
         if (mx==p1)
         {
              x[i][4]=x[i][1]+x[i][2]-x[i][3];
              y[i][4]=y[i][1]+y[i][2]-y[i][3];
         }
         if (mx==p2)
         {
              x[i][4]=x[i][1]+x[i][3]-x[i][2];
              y[i][4]=y[i][1]+y[i][3]-y[i][2];
         }
         if (mx==p3)
         {
              x[i][4]=x[i][2]+x[i][3]-x[i][1];
              y[i][4]=y[i][2]+y[i][3]-y[i][1];
         }
         for (intj=1;j<=4;j++)  //加点;
         {
            cnt++;
              e[cnt].x=x[i][j];
              e[cnt].y=y[i][j];
              q[i].pos[j]=cnt;    //记录每个城市包含的点;
              for (intk=0;k<j;k++)   //城市内部点之间连边;
             {
                   dist[cnt][cnt-k]=dis(e[cnt].x,e[cnt].y,e[cnt-k].x,e[cnt-k].y)*t[i];
                   dist[cnt-k][cnt]=dist[cnt][cnt-k];
              }
         }
         for (intj=1;j<=cnt-4;j++)    //不同城市的点之间连边;
         {
              intsx=e[j].x,sy=e[j].y;
              for (intk=0;k<=3;k++)  //这一重循环一定要在上一重里面,不能提出去用,这个(2,+ ∞)的bug卡了我半小时TAT……
              {
                   intrx=e[cnt-k].x,ry=e[cnt-k].y;
                   dist[j][cnt-k]=dis(sx,sy,rx,ry)*p;
                   dist[cnt-k][j]=dist[j][cnt-k];
              }
         }
     }
//floyd算法:
     for (intk=1;k<=cnt;k++)
      for (int i=1;i<=cnt;i++)
      for (intj=1;j<=cnt;j++)
         dist[i][j]=min(dist[i][k]+dist[k][j],dist[i][j]);
double mi=210000000;
//枚举出发城市和目的城市的点,取最小值:
     for (inti=1;i<=4;i++)
    {
       int t1=q[a].pos[i];
       for (int j=1;j<=4;j++)
       {
            int t2=q[b].pos[j];
            if(dist[t1][t2]<mi) mi=dist[t1][t2];
         }
     }
     printf("%.1f",mi);  //注意精度;
     return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值