题目描述

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

图例(从上而下)

机场 高速铁路

飞机航线

  注意:图中并没有

标出所有的铁路与航线。

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

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

输入输出格式

输入格式:

第一行为一个正整数n(0<=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个城市中任意三个机场的坐标,T I为第I个城市高速铁路单位里程的价格。

输出格式:

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

输入输出样例

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

最短路。

对于每个城市,根据已知的三个点坐标算出第四个点坐标,然后在同一城市的点之间两两连边(高铁),在不同城市的点之间两两连边(飞机),跑最短路即可。如何算第四个点的坐标?

首先由于四个点构成矩形,已知的三个点必构成直角三角形。通过比较三条边的长度可以找到直角顶点。具体看代码。

 /*by SilverN*/
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
const int mxn=;
int read(){
int x=,f=;char ch=getchar();
while(ch<'' || ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>='' && ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
double dist(int x1,int y1,int x2,int y2){
return sqrt( (double)(x1-x2)*(x1-x2)+(double)(y1-y2)*(y1-y2) );
}
struct node{//点集
int x,y;
}a[mxn],p[];
int ncnt=;
int pdd(){//找直角边顶点
double d12=dist(p[].x,p[].y,p[].x,p[].y);
double d23=dist(p[].x,p[].y,p[].x,p[].y);
double d13=dist(p[].x,p[].y,p[].x,p[].y);
if(d12>d23 && d12>d13)return ;
if(d23>d12 && d23>d13)return ;
if(d13>d23 && d13>d12)return ;
}
void pos4(int tp){//算第四个点坐标
switch(tp){//根据直角顶点讨论。其实如果先把直角顶点swap到p[1]位置,代码可以更精简
case :{
p[].x=p[].x+p[].x-p[].x;
p[].y=p[].y+p[].y-p[].y;
break;
}
case :{
p[].x=p[].x+p[].x-p[].x;
p[].y=p[].y+p[].y-p[].y;
break;
}
case :{
p[].x=p[].x+p[].x-p[].x;
p[].y=p[].y+p[].y-p[].y;
break;
}
}
return;
}
struct edge{
int v,nxt;
double dis;
}e[mxn];
int hd[mxn],mct=;
void add_edge(int u,int v,double dis){
e[++mct].v=v;e[mct].dis=dis;e[mct].nxt=hd[u];hd[u]=mct;
return;
} int N;
int n,w,A,B; queue<int>q;
double dis[mxn];
bool inq[mxn];
void SPFA(int s){//最短路
for(int i=;i<=ncnt;i++)dis[i]=;
dis[s]=;inq[s]=;
q.push(s);
int i,j;
while(!q.empty()){
int u=q.front();q.pop();inq[u]=;
for(i=hd[u];i;i=e[i].nxt){
int v=e[i].v;
if(dis[v]>dis[u]+e[i].dis){
dis[v]=dis[u]+e[i].dis;
if(!inq[v]){
inq[v]=;
q.push(v);
}
}
}
}
return;
}
int main(){
int i,j;
N=read();
while(N--){
memset(a,,sizeof a);
memset(e,,sizeof e);
memset(hd,,sizeof hd);
mct=ncnt=;
//
n=read();
w=read();A=read();B=read();
int X1,X2,X3,Y1,Y2,Y3,tt;
for(i=;i<=n;++i){
p[].x=read();p[].y=read();
p[].x=read();p[].y=read();
p[].x=read();p[].y=read();
tt=read();
pos4(pdd());
for(j=;j<=;j++)
for(int k=;k<=;k++){
if(k!=j)add_edge(ncnt+j,ncnt+k,dist(p[j].x,p[j].y,p[k].x,p[k].y)*tt);
}
for(j=;j<=;j++){
for(int k=;k<=ncnt;k++){
double dd=dist(p[j].x,p[j].y,a[k].x,a[k].y)*w;
add_edge(ncnt+j,k,dd);
add_edge(k,ncnt+j,dd);
}
}
for(j=;j<=;j++){a[++ncnt]=p[j];}
}
double ans=;
int st=(A-)*;
for(i=;i<=;i++){
SPFA(st+i);
int ed=(B-)*;
for(j=;j<=;j++){
// printf("%d to %d dis:%.1f\n",st+i,ed+j,dis[ed+j]);
ans=min(ans,dis[ed+j]);
}
}
printf("%.1f\n",ans);
}
return ;
}

[NOIP2001] 提高组 洛谷P1027 Car的旅行路线的更多相关文章

  1. 洛谷P1027 Car的旅行路线

    洛谷P1027 Car的旅行路线 题目描述 又到暑假了,住在城市A的Car想和朋友一起去城市B旅游.她知道每个城市都有四个飞机场,分别位于一个矩形的四个顶点上,同一个城市中两个机场之间有一条笔直的高速 ...

  2. 洛谷 P1027 Car的旅行路线

    P1027 Car的旅行路线 题目描述 又到暑假了,住在城市A的Car想和朋友一起去城市B旅游.她知道每个城市都有四个飞机场,分别位于一个矩形的四个顶点上,同一个城市中两个机场之间有一条笔直的高速铁路 ...

  3. 洛谷 P1027 Car的旅行路线 最短路+Dijkstra算法

    目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例 输出样例 说明 思路 AC代码 总结 题面 题目链接 P1027 Car的旅行路线 题目描述 又到暑假了,住在 ...

  4. [NOIP2001] 提高组 洛谷P1026 统计单词个数

    题目描述 给出一个长度不超过200的由小写英文字母组成的字母串(约定;该字串以每行20个字母的方式输入,且保 证每行一定为20个).要求将此字母串分成k份(1<k<=40),且每份中包含的 ...

  5. [NOIP2001] 提高组 洛谷P1025 数的划分

    题目描述 将整数n分成k份,且每份不能为空,任意两个方案不相同(不考虑顺序). 例如:n=7,k=3,下面三种分法被认为是相同的. 1,1,5; 1,5,1; 5,1,1; 问有多少种不同的分法. 输 ...

  6. [NOIP2001] 提高组 洛谷P1024 一元三次方程求解

    题目描述 有形如:ax3+bx2+cx+d=0 这样的一个一元三次方程.给出该方程中各项的系数(a,b,c,d 均为实数),并约定该方程存在三个不同实根(根的范围在-100至100之间),且根与根之差 ...

  7. 洛谷——P1027 Car的旅行路线

    https://www.luogu.org/problem/show?pid=1027#sub 题目描述 又到暑假了,住在城市A的Car想和朋友一起去城市B旅游.她知道每个城市都有四个飞机场,分别位于 ...

  8. [NOIP2015] 提高组 洛谷P2615 神奇的幻方

    题目描述 幻方是一种很神奇的N*N矩阵:它由数字1,2,3,……,N*N构成,且每行.每列及两条对角线上的数字之和都相同. 当N为奇数时,我们可以通过以下方法构建一个幻方: 首先将1写在第一行的中间. ...

  9. [NOIP2014] 提高组 洛谷P2038 无线网络发射器选址

    题目描述 随着智能手机的日益普及,人们对无线网的需求日益增大.某城市决定对城市内的公共场所覆盖无线网. 假设该城市的布局为由严格平行的129 条东西向街道和129 条南北向街道所形成的网格状,并且相邻 ...

随机推荐

  1. AJPFX总结Collection集合(下)

    List集合特有方法 特有方法.凡是可以操作角标的方法都是该体系特有的方法. 增          add(index,element);在指定位置添加元素          addAll(index ...

  2. jdk1.8新日期时间类(DateTime、LocalDateTime)demo代码

    //获取当前时间 LocalDateTime d0 = LocalDateTime.now(); System.out.println(DataConvertUtil.localDateTimeToS ...

  3. JavaFX Chart设置数值显示

    一.XYChart import javafx.application.Application;import javafx.geometry.NodeOrientation;import javafx ...

  4. ArrayList Vector LinkedList分析

    1.创建 ArrayList 的底层是一个数组.  ArrayList<String> list1 = new ArrayList<>(); list1.add("a ...

  5. docker新手入门(基本命令以及介绍)

    Docker 的核心内容 镜像 (Image) 容器 (Container) 仓库 (Repository) Registry 用来保存用户构建的镜像 docker的开始使用: 1. docker  ...

  6. Windows API函数大全(完整)

    Windows API函数大全,从事软件开发的朋友可以参考下 1. API之网络函数 WNetAddConnection 创建同一个网络资源的永久性连接 WNetAddConnection2 创建同一 ...

  7. Open Cascade:使用鼠标画线

    Open Cascade:使用鼠标画线 在View类文件中创建以下代码: 1.创建鼠标消息: afx_msg void OnLButtonDown(UINT nFlags, CPoint point) ...

  8. java程序在一个电脑上只启动一次,只开一个进程

    方案1: 单进程程序可以用端口绑定.程序启动的时候可以尝试看该端口是否已经被占用,如果占用则程序已经启动. 方案2:你可以在java程序中创建一个隐藏文件,程序退出的时候删除这个文件.这样在程序启动的 ...

  9. SFM作业

    代码:https://github.com/jianxiongxiao/SFMedu PPT:http://3dvision.princeton.edu/courses/SFMedu/slides.p ...

  10. 安装Yii2提示Failed to decode response: zlib_decode(): data error错误解决方法

    如果是根据官方文档来安装(composer create-project --prefer-dist yiisoft/yii2-app-basic basic),并提示此错误的话,那么请做: 1. 请 ...