牛客 NC16697 [NOIP2001]Car的旅行路线

题目描述

又到暑假了,住在城市A的Car想和朋友一起去城市B旅游。她知道每个城市都有四个飞机场,分别位于一个矩形的四个顶点上,同一个城市中两个机场之间有一条笔直的高速铁路,第I个城市中高速铁路了的单位里程价格为Ti,任意两个不同城市的机场之间均有航线,所有航线单位里程的价格均为t。

 

图例(从上而下)

机场

高速铁路
飞机航线

注意:图中并没有标出所有的铁路与航线。

那么Car应如何安排到城市B的路线才能尽可能的节省花费呢?她发现这并不是一个简单的问题,于是她来向你请教。
任务:找出一条从城市A到B的旅游路线,出发和到达城市中的机场可以任意选取,要求总的花费最少。

输入描述:

第一行为一个正整数n( 0 ≤ n ≤ 10 ),表示有n组测试数据。
每组的第一行有4个正整数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个城市中任意3个机场的坐标,Ti 为第i个城市高速铁路单位里程的价格。

输出描述:

共有n行,每行1个数据对应测试数据(最小花费)。保留一位小数。

示例1

输入

复制

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.5

思路:可以直接将一个城市看为四个点,然后建边跑最短路算法即可,我用的是floyd算法

AC代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;

const int N=410;

double d[N][N];
int n,fee,S,E,t;
struct Node{
	int x,y,fee;
}a[N*4];
struct City{
	int x[4],y[4],price;
}city[110];

double getDist(int x,int y,int x1,int y1)
{
	double xx=x-x1,yy=y-y1;
	return sqrt(xx*xx+yy*yy);
}

void getCity4(City &a)//找到第四个点
{
	double d[3];
	for(int i=0,k=0;i<3;i++)
		for(int j=i+1;j<3;j++)
			d[k++]=getDist(a.x[i],a.y[i],a.x[j],a.y[j]);
	double maxx=max({d[0],d[1],d[2]});
	for(int i=0;i<3;i++)
		if(maxx==d[i])
		{
			int k=2-i;
			int x=0,y=0;
			for(int j=0;j<3;j++)
				if(j!=k)
					x+=a.x[j],y+=a.y[j];
			a.x[3]=x-a.x[k];
			a.y[3]=y-a.y[k];
			break;
		}
}

int main()
{
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d%d%d",&n,&fee,&S,&E);
		S--,E--;
		for(int i=1;i<=n;i++)
		{
			for(int j=0;j<3;j++)
				scanf("%d%d",&city[i].x[j],&city[i].y[j]);
			scanf("%d",&city[i].price);
			getCity4(city[i]);
			for(int j=0;j<4;j++)
				a[(i-1)*4+j+1]={city[i].x[j],city[i].y[j],city[i].price};
		}
		
		for(int i=1;i<=4*n;i++)
			for(int j=i+1;j<=4*n;j++)
				if((i-1)/4==(j-1)/4)
					d[i][j]=d[j][i]=a[i].fee*getDist(a[i].x,a[i].y,a[j].x,a[j].y);
				else
					d[i][j]=d[j][i]=fee*getDist(a[i].x,a[i].y,a[j].x,a[j].y);
		
		for(int k=1;k<=4*n;k++)
			for(int i=1;i<=4*n;i++)
				for(int j=1;j<=4*n;j++)
					d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
				
		double res=1e18;
		for(int i=1;i<=4;i++)
			for(int j=1;j<=4;j++)
				res=min(res,d[S*4+i][E*4+j]);
		
		printf("%.1lf\n",res);
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Double.Qing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值