平行旅行【最短路】【贪心】

>Link

牛客1030普及T2


>Description
给出一个有n个点的图,每个点都有对应的坐标
其中每两个点之间都有且仅有一条路径,路径长为两点间的哈密顿距离
这n个点中有m个固定的点,我们可以在任何时候任意位置花费0代价到达这m个点中的任何一个
要求求一条最短路,这条路径中一定存在1、2、3…n的到达顺序


>解题思路
两点之间的路径权值为哈密顿距离,因此我们知道从 i i i步行到 j j j的最短路一定是直接走两点之间的那一条路径
传送门的情况,我们就直接O(nm)暴力求出从每个传送门到每个点的最优代价,原理同上
最后答案就累加每 [ i , i + 1 ] [i,i+1] [i,i+1]之间的最短距离


>代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define N 5005
#define int long long
using namespace std;

int n, m, x[N], y[N], s[N], dis[N][N], minn[N], ans;
bool mark[N];

signed main()
{
	memset (minn, 0x7f, sizeof (minn));
	scanf ("%lld%lld", &n, &m);
	for (int i = 1; i <= n; i++) scanf ("%lld%lld", &x[i], &y[i]);
	for (int i = 1; i <= m; i++)
	{
		scanf ("%lld", &s[i]);
		mark[s[i]] = 1;
	}
	for (int i = 1; i <= m; i++)
	  for (int j = 1; j <= n; j++)
	    if (!mark[j])
		  minn[j] = min (minn[j], abs (x[s[i]] - x[j]) + abs (y[s[i]] - y[j]));
		  
	for (int i = 1; i < n; i++)
	{
		if (mark[i + 1]) continue;
		ans += min (minn[i + 1], abs (x[i] - x[i + 1]) + abs (y[i] - y[i + 1]));
		//要么用传送门,要么直接步行
	}
	printf ("%lld", ans);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值