ZZULIOJ 3021: 异次元空间

题目描述:

小Z是一个非常喜欢冒险的美食家,经常游走在各地寻找美食。这一天,他像往常一样前往城镇A寻找远近闻名的甜甜花酿鸡,却不慎掉入了异次元空间(不是提瓦特大陆),他想尽快找到出口,却发现这里和真实的世界有些不同...

这个世界有许多城镇,每一个城镇都有一个二维坐标,某两个城镇之间有道路相连,道路的长度不一定是欧氏距离(直线距离),而是 Lk 范数。小Z的初始位置在城镇 A ,异次元空间出口所在的位置在城镇 Z ,现在问你小Z应该最少走多远才能到达出口。

关于 Lk 范数:对于任意两个城镇 A(x1,y1),B(x2,y2) 的 Lk 范数为 (|x1-x2|^k+|y1-y2|^k)^(1 / k)

提示:若存在三个城镇 A、B、C,Pk(X,Y) 表示城镇 X 和 Y 的 Lk 范数,则 Pk(A,C)≤Pk(A,B)+Pk(B,C) (三角不等式)

输入:

第一行三个整数 n,m,k(2 ≤ n ≤ 10000,0 ≤ m ≤ min(n(n-1)/2,10000),1 ≤ k ≤ 6)
分别表示异次元空间中一共存在 n 个村庄,m 条道路,Lk 范数中的 k

随后 n 行每行两个整数 x,y(−200≤x,y≤200) 表示 n 个城镇的坐标
城镇 A 在第二行,城镇 Z 在第 n+1 行

接着 m 行每行两个数 u,v(1≤u,v≤n) 表示城镇 u 和城镇 v 之间存在道路

不保证数据不存在自环、重边、重点

输出:

一个数字表示从城镇 A 到城镇 Z 的最短距离,保存两位小数;若无法到达输出 -1.00

样例输入:

3 3 1
0 0
1 0
1 1
1 2
2 3
1 3

样例输出 

2.00

提示

由于k=1,因此两城镇间的距离计算公式为∣x1−x2∣+∣y1−y2∣。三个城镇的坐标分别为A(0,0)、B(1,0)、Z(1,1),并且两两之间存在道路连接,因此城镇A可以直接到达城镇Z,距离为2.00。

来源/分类

郑州轻工业大学2022级新生程序设计大赛暨省内高校邀请赛

思路:

本题就是一个很典型的最短路模型,由于边权均是正数,这里使用Dijkstra算法进行求解,并用heap进行优化

本道题应该是无向边,博主写了好久一直AC ,然后同学提醒发现是无向边(- _ -)

#include<iostream>
#include<queue>
#include<vector>
#include<algorithm>
#include<cstring>

using namespace std;

typedef pair<double, int>PII;

const int N = 10010, INF = 0x3f3f3f3f;
int h[N], e[N * 2], idx = 0, ne[N * 2];
double w[N * 2];
int n, m, k;
double dist[N];
bool st[N];

void add(int a, int b, double c)
{
	e[idx] = b;
	w[idx] = c;
	ne[idx] = h[a];
	h[a] = idx++;
}

double dijkstra()
{
	for (int i = 0; i <= N-1; i++) dist[i] = (double)INF;

	priority_queue<PII, vector<PII>, greater<PII>> heap;

	dist[1] = 0;
	heap.push({ 0.00, 1 });
	while (!heap.empty())
	{
		auto t = heap.top();
		heap.pop();

		int a = t.second;

		if (st[a]) continue;
		st[a] = 1;

		for (int i = h[a]; i!=-1; i = ne[i])
		{
			int j = e[i];
			if (dist[j] > dist[a] + w[i])
			{
				dist[j] = dist[a] + w[i];
				heap.push({ dist[j],j });
			}
		}
	}
	return dist[n];
}

int main()
{
	cin >> n >> m >> k;
	PII a[N];
	for (int i = 1; i <= n; i++) cin >> a[i].first >> a[i].second;
	
	memset(h, -1, sizeof h);

	while (m--)
	{
		int p, q;
		cin >> p >> q;
		double c = (double)pow((double)pow((double)abs(a[p].first - a[q].first), k)+ (double)pow((double)abs(a[p].second - a[q].second), k),1.00/(double)k);
		add(p, q, c);
		add(q, p, c);
	}

	double d = dijkstra();

	if (d == (double)INF) cout << "-1.00" << endl;
	else printf("%.2lf", d);

	return 0;
}

  • 13
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值