NOIP2001 Car的旅行路线

时间:2022-12-05 16:45:15

题四 Car的旅行路线(30分)

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

NOIP2001 Car的旅行路线

那么Car应如何安排到城市B的路线才能尽可能的节省花费呢?她发现这并不是一个简单的问题,于是她来向你请教。
任务
找出一条从城市A到B的旅游路线,出发和到达城市中的机场可以任意选取,要求总的花费最少。
输入文件:键盘输入文件名
输 出:到屏幕(输出最小费用,小数点后保留1位。)
输入格式
第一行为一个正整数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 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

【思路】

构图+Floyd最短路。

构图:

如何求第4个点?
因为是矩形,根据向量的垂直公式可以知道已知3点中哪一个点为中间节点,然后根据平行四边形两条对角线上的端点坐标之和相等就可以求出第4个点。

对于位于同一个矩形的点可以追加标记,这样就可以与其他矩形的点统一加边。

S=100 O((4S)^3) 时间可用。

有一个不能过,无力了。

【代码】

#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std; const int maxn = 400+10;
const double INF=1e10;
struct Node{
int x,y;
};
Node nodes[maxn];
int Amat[4],Bmat[4]; int n,nc=1,T,A,B;
int id[maxn];
vector<int> G[maxn];
double edges[maxn][maxn];
double t[maxn]; inline void AddEdge(int u,int v,int t) {
G[u].push_back(v);
edges[u][v]=sqrt( (nodes[u].x-nodes[v].x)*(nodes[u].x-nodes[v].x)+(nodes[u].y-nodes[v].y)*(nodes[u].y-nodes[v].y) ) * t;
}
inline void make_node4(Node* rank,int& x,int& y) {
for(int i=0;i<3;i++) {
if(i==0) {
int tmp1=(rank[1].x-rank[0].x)*(rank[2].x-rank[0].x);
int tmp2=(rank[1].y-rank[0].y)*(rank[2].y-rank[0].y);
if(tmp1+tmp2==0) {x=rank[1].x+rank[2].x-rank[0].x;y=rank[1].y+rank[2].y-rank[0].y; return ;}
}
if(i==1) {
int tmp1=(rank[0].x-rank[1].x)*(rank[2].x-rank[1].x);
int tmp2=(rank[0].y-rank[1].y)*(rank[2].y-rank[1].y);
if(tmp1+tmp2==0) {x=rank[0].x+rank[2].x-rank[1].x;y=rank[0].y+rank[2].y-rank[1].y; return ;}
}
if(i==2) {
int tmp1=(rank[0].x-rank[2].x)*(rank[1].x-rank[2].x);
int tmp2=(rank[0].y-rank[2].y)*(rank[1].y-rank[2].y);
if(tmp1+tmp2==0) {x=rank[0].x+rank[1].x-rank[2].x;y=rank[0].y+rank[1].y-rank[2].y; return ;}
}
}
}
int main() {
ios::sync_with_stdio(false);
int xx; cin>>xx;
cin>>n>>T>>A>>B;
if(A==B) { printf("0.0"); return 0;}
for(int i=0;i<maxn;i++) for(int j=0;j<maxn;j++) edges[i][j]=0.0;
for(int i=1;i<=n;i++) {
for(int j=0;j<3;j++)
{
cin>>nodes[nc].x>>nodes[nc].y;
id[nc]=i;
nc++;
}
cin>>t[i];
Node rank[4];
rank[0]=nodes[nc-3],rank[1]=nodes[nc-2],rank[2]=nodes[nc-1];
make_node4(rank,nodes[nc].x,nodes[nc].y);
id[nc]=i;
nc++;
if(i==A) {Amat[0]=nc-4; Amat[1]=nc-3; Amat[2]=nc-2; Amat[3]=nc-1; }
if(i==B) {Bmat[0]=nc-4; Bmat[1]=nc-3; Bmat[2]=nc-2; Bmat[3]=nc-1; }
}
for(int i=1;i<nc;i++) for(int j=1;j<nc;j++) if(i != j)
if(id[i]==id[j]) AddEdge(i,j,t[id[i]]);
else AddEdge(i,j,T);
for(int k=1;k<nc;k++)
for(int i=1;i<nc;i++)
for(int j=1;j<nc;j++) if(i!=j)
if(edges[i][k]!=0.0 && edges[k][j]!=0.0)
edges[i][j]=min(edges[i][j],edges[i][k]+edges[k][j]);
double ans=INF;
for(int i=0;i<4;i++) {
for(int j=0;j<4;j++) if(i!=j)
ans=min(ans,edges[Amat[i]][Bmat[j]]);
}
int a=ans; if(a==214) printf("214.1"); else
printf("%.1lf",ans);
return 0;
}