问题描述
又到暑假了,住在城市A的Car想和朋友一起去城市B旅游。她知道每个城市都有四个飞机场,分别位于一个矩形的四个顶点上,同一个城市中两个机场之间有一 条笔直的高速铁路,第I个城市中高速铁路了的单位里程价格为Ti,任意两个不同城市的机场之间均有航线,所有航线单位里程的价格均为t。
那么Car应如何安排到城市B的路线才能尽可能的节省花费呢?她发现这并不是一个简单的问题,于是她来向你请教。
找出一条从城市A到B的旅游路线,出发和到达城市中的机场可以任意选取,要求总的花费最少。
输入格式
的第一行有四个正整数s,t,A,B。
S表示城市的个数,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 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
数据规模和约定
0<S<=100
这一题是典型最短路问题,可采用dijkstra或floyd算法,但前面的预处理过程有些繁琐,另外这题只给了三个坐标点,还需要用迭代求另一个坐标点…,利用垂直关系((y1 - y2) / (x1 - x2)) * ((y2 - y3) /(x2 - x3) = -1;求解。
代码如下:
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#define INF 0x3f3f3f
#define CTOA(x) (((x - 1) << 2) + 1)//左移位操作, 区分不同类的机场
#define DISTANCE(x1, y1, x2, y2) ((double) sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)))
using namespace std;
double node[4050][4050];//node[i][j] i 到 j 点的距离
double T;
int tx[3], ty[3], t;
double ans = INF;
struct city{
int x[4], y[4];
}ct[105];//ct[i].x[j] = 第i个城市第j个机场的横坐标, ct[i].y[j] = 第i个城市第j个机场的纵坐标
void GetfourPosition(int c)
{
int tt;
// memcpy 表示内存拷贝函数
memcpy(tx, ct[c].x, sizeof(tx));
memcpy(ty, ct[c].y, sizeof(ty));
// 只需对tx, ty进行操作tx[0], tx[1]..., ty[0], ty[1]...
// 迭代
while((tx[0] - tx[1]) * (tx[2] - tx[1]) + (ty[0] - ty[1]) * (ty[2] - ty[1]))//找直角边((x1 - x2) / (y1 - y2)) * ((x3 - x2) / (y3 - y2)) = -1;
{
tt = tx[0]; tx[0] = tx[1]; tx[1] = tx[2]; tx[2] = tt;
tt = ty[0]; ty[0] = ty[1]; ty[1] = ty[2]; ty[2] = tt;//直至AB⊥BC
}
ct[c].x[3] = tx[0] - tx[1] + tx[2];
ct[c].y[3] = ty[0] - ty[1] + ty[2];
}
int main()
{
int i, j, k, l, m;
int s, t, a, b;
scanf("%d%d%d%d", &s, &t, &a, &b);
if(a == b)
{
printf("0.0\n"); return 0;//同一个城市, 距离为0
}
int airport = s << 2;//左移两位, airport = 机场数量
for(i = 1; i <= airport; ++i)
{
for(j = 1; j <= airport; ++j) node[i][j] = INF;
}
for(i = 1; i <= s; ++i)
{
for(j = 0; j < 3; ++j) scanf("%d%d", &ct[i].x[j], &ct[i].y[j]);
scanf("%lf", &T);
GetfourPosition(i);//difficult
for(j = 0; j < 4; ++j)
for(k = 0; k < 4; ++k)
{
if(j != k) node[CTOA(i) + j][CTOA(i) + k] = (DISTANCE(ct[i].x[k], ct[i].y[k], ct[i].x[j], ct[i].y[j])) * T;
}
}
for(i = 1; i <= s; ++i)
for(j = 1; j <= s; ++j)
{
if(i != j)
{
for(k = 0; k < 4; ++k)//i 城市 第 k 个机场
for(l = 0; l < 4; ++l)//j 城市 第 l 个机场
{
node[CTOA(i) + k][CTOA(j) + l] = (DISTANCE(ct[i].x[k], ct[i].y[k], ct[j].x[l], ct[j].y[l])) * t;
}
}
}
// 前面为预处理过程, 核心算法floyd
for(k = 1; k <= airport; ++k)
for(i = 1; i <= airport; ++i)
for(j = 1; j <= airport; ++j)
{
node[i][j] = min(node[i][j], node[i][k] + node[k][j]);
}
for(i = 0; i < 4; ++i)
for(j = 0; j < 4; ++j)
{
ans = min(ans, node[CTOA(a) + i][CTOA(b) + j]);
}
printf("%.1f\n", ans);
return 0;
}
/*
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
*/