当前位置: 首页 > article >正文

2024/11/3 随笔笔记

[NOIP2001 提高组] Car 的旅行路线

题目描述

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

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

那么 Car 应如何安排到城市 B 的路线才能尽可能的节省花费呢?她发现这并不是一个简单的问题,于是她来向你请教。

找出一条从城市 A 到 B 的旅游路线,出发和到达城市中的机场可以任意选取,要求总的花费最少。

输入格式

第一行为一个正整数 n n n,表示有 n n n 组测试数据。

每组的第一行有 4 4 4 个正整数 S , t , A , B S,t,A,B S,t,A,B

S S S 表示城市的个数, t t t 表示飞机单位里程的价格, A A A B B B 分别为城市A,B 的序号。

接下来有 S S S 行,其中第 i i i 行均有 7 7 7 个正整数 x i 1 , y i 1 , x i 2 , y i 2 , x i 3 , y i 3 , T i x_{i1},y_{i1},x_{i2},y_{i2},x_{i3},y_{i3},T_i xi1,yi1,xi2,yi2,xi3,yi3,Ti,这当中的 ( x i 1 , y i 1 ) , ( x i 2 , y i 2 ) , ( x i 3 , y i 3 ) (x_{i1},y_{i1}), (x_{i2},y_{i2}), (x_{i3},y_{i3}) (xi1,yi1),(xi2,yi2),(xi3,yi3),分别是第 i i i 个城市中任意 3 3 3 个机场的坐标, T i T_i Ti 为第 i i i 个城市高速铁路单位里程的价格。

输出格式

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

样例 #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

样例输出 #1

47.5

提示

【数据范围】
对于 100 % 100\% 100% 的数据, 1 ≤ n ≤ 10 1\le n \le 10 1n10 1 ≤ S ≤ 100 1\le S \le 100 1S100 1 ≤ A , B ≤ S 1\le A,B \le S 1A,BS

【题目来源】

NOIP 2001 提高组第四题

思路:重点来了,一般来讲我们要分析数据范围,S<=100 ,在最短路的算法里面可以用单源最短路也可以用floyed这种O(n^3)的暴力算法求解,对于题目中的要求,我们必须要把同一座城市的四个机场坐标全部算出来,很明显,对于只给了三个点的城市坐标来说,我们可以通过勾股定理确定哪条边是斜边,哪条边是直边,进而求出第四个点的坐标,这里我给个推导过程。

我们用勾股定理确定斜边与直角边 a b 2 + b c 2 = c d 2 我们用勾股定理确定斜边与直角边 ab^{2} +bc^{2}=cd^{2} 我们用勾股定理确定斜边与直角边ab2+bc2=cd2

然后可以从已知的三个边中找出斜边,也就是说 c d 点的中点是与 a b 的中点重合那么就有 然后可以从已知的三个边中找出斜边,也就是说cd点的中点是与ab的中点重合 那么就有 然后可以从已知的三个边中找出斜边,也就是说cd点的中点是与ab的中点重合那么就有

{ a x + b x = c x + d x a y + b y = c y + d y {\Huge \begin{cases} a_{x} +b_{x}=c_{x}+d_{x} \\ a_{y}+b_{y}=c_{y}+d_{y} \end{cases}} ax+bx=cx+dxay+by=cy+dy

而且我们知道其中三个点的坐标那么我们就可以反推出第四个点的坐标 而且我们知道其中三个点的坐标那么我们就可以反推出第四个点的坐标 而且我们知道其中三个点的坐标那么我们就可以反推出第四个点的坐标
{ d x = a x + b x − c x d y = c y + a y + b y {\Huge \begin{cases} d_{x}=a_{x} +b_{x}-c_{x} \\ d_{y}=c_{y}+a_{y}+b_{y} \end{cases}} dx=ax+bxcxdy=cy+ay+by

把所有的点的坐标算出来之后,我们就可以开始对dist这个数组开始进行处理了,首先我们要考虑是否可以直接用floyed求解,理论上来说是可以的,但是这里不推荐,因为如果直接进行floyed的话我们需要对中转点进行讨论,考虑到三个点需要进行是否在一个城市的讨论,这里涉及情况非常多,于是我们需要从两个点开始出发进行对数组的初始化,对于两个点来说,讨论他们的情况只有两种,要么这两个点在一个城市里,要不不在一个城市里,这两种情况通过坐标的存储技巧就可以简单化解。

最后就可以直接暴力的floyed,因为这个时候任意两个点之间都有直接到达的值,这样子floyed就无需再进行讨论了。

code

#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#include<cmath>
using namespace std;
typedef long long ll;
typedef double ld;
const int N=111;
int n;
int S,A,B;
ld t,T[N];
ld x[N<<3],y[N<<3];
ld dis[N<<3][N<<3];
ld ab,ac,bc;//求D点 
ld ans;
ld dist(ld x1,ld y1,ld x2,ld y2)
{
	return (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
}
int main()
{
	
	scanf("%d",&n);
	while(n--)
	{
		ans=1e9;
		memset(dis,0,sizeof(dis));
		scanf("%d%lf%d%d",&S,&t,&A,&B);
		for(int i=1;i<=S;++i)
			{
				for(int j=1;j<=3;++j) 
					scanf("%lf%lf",&x[((i-1)*4)+j],&y[((i-1)*4)+j]);
				scanf("%lf",&T[i]);	
			}		
			
		for(int i=1;i<=S;++i)
		{
			ab=dist(x[(i-1)*4+1],y[(i-1)*4+1],x[(i-1)*4+2],y[(i-1)*4+2]);
			bc=dist(x[(i-1)*4+2],y[(i-1)*4+2],x[(i-1)*4+3],y[(i-1)*4+3]);
			ac=dist(x[(i-1)*4+1],y[(i-1)*4+1],x[(i-1)*4+3],y[(i-1)*4+3]);
			//运用勾股找出中心点 
			if(ab+bc==ac)
				x[i*4]=x[(i-1)*4+1]+x[(i-1)*4+3]-x[(i-1)*4+2],y[i*4]=y[(i-1)*4+1]+y[(i-1)*4+3]-y[(i-1)*4+2];
			if(ab+ac==bc)
				x[i*4]=x[(i-1)*4+2]+x[(i-1)*4+3]-x[(i-1)*4+1],y[i*4]=y[(i-1)*4+2]+y[(i-1)*4+3]-y[(i-1)*4+1];
			if(ac+bc==ab)
				x[i*4]=x[(i-1)*4+1]+x[(i-1)*4+2]-x[(i-1)*4+3],y[i*4]=y[(i-1)*4+1]+y[(i-1)*4+2]-y[(i-1)*4+3];
		}
		//初始化 
		for(int i=1;i<=(S<<2);++i)
		for(int j=1;j<=(S<<2);++j)
		{
			if(i!=j)
			{
				if((i-1)/4==(j-1)/4)//说明在同一座城市 
				  dis[i][j]=sqrt(dist(x[i],y[i],x[j],y[j]))*T[((i-1)/4)+1]*1.0;
				else dis[i][j]=sqrt(dist(x[i],y[i],x[j],y[j]))*t*1.0;
			}
		}
		for(int k=1;k<=(S<<2);++k)
		for(int i=1;i<=(S<<2);++i)
		for(int j=1;j<=(S<<2);++j) dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
		
		for(int i=1;i<=4;++i)
		for(int j=1;j<=4;++j) ans=min(dis[(A-1)*4+i][(B-1)*4+j],ans);
		printf("%.1f",ans);
	}
	
	return 0;
} 

http://www.kler.cn/a/379479.html

相关文章:

  • uniapp 使用vue/pwa
  • 【Linux】命令行参数 | 环境变量
  • WordPress之generatepress主题安装
  • Java环境下配置环境(jar包)并连接mysql数据库
  • VSCode 1.82之后的vscode server离线安装
  • 11.4工作笔记
  • 深度学习笔记之BERT(一)BERT的基本认识
  • 利用Spring Boot框架打造信息学科平台
  • Golang | Leetcode Golang题解之第520题检测大写字母
  • GitHub、Gitee、GitLab介绍
  • [spring源码]spring推断构造方法
  • 【深入浅出】深入浅出Bert(附面试题)
  • Ubuntu 开通 SSH 连接方式指南
  • 论文阅读笔记Dense Passage Retrieval for Open-Domain Question Answering
  • 突破自闭症治疗的创新方法和评估
  • 数据库动态扩容:Java实现与技术策略
  • Spring Boot——配置文件
  • 基于Python的乡村居民信息管理系统【附源码】
  • 国自然基金项目撰写技巧
  • LeetCode100之盛最多水的容器(11)--Java
  • 【JAVA】第3关:素数链
  • HJ43 迷宫问题
  • 虚拟机安装
  • 危机来临前---- 力扣: 876
  • 双指针-01-三数之和
  • LeetCode:3259. 超级饮料的最大强化能量(DP Java)