算法训练 Car的旅行路线(最短路)

问题描述
  又到暑假了,住在城市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
*/
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值