题目描述
你是一只青蛙,现在处于一个无穷大的网格中,现在你所在的点坐标是 (xMe,yMe),你的目标是跳到点 (xHome,yHome)。你有两种不同的跳跃方式,第一种是:如果你现在的点坐标是 (x,y),你跳一步能跳到相邻的四个点:(x+1,y),(x−1,y),(x,y+1) 或者 (x,y−1),每跳一步需要一秒;第二种跳跃方式是:使用超级工具 teleport,在整个网格中有 3 个 teleport, 每一个 teleport 连接两个不同的点。 如果你在某个 teleport 的一端,那么你可以使用该 teleport 跳到另一端,需要花费的时间是 10 秒。作为一只青蛙,请输出回家所用的最少时间。注意:teleport 不是强制使用的,你到达某个 teleport 的端点时,你可以不用 teleport 而是用第一种跳跃方式。
输入格式 1778.in
多组测试数据。
第一行,一个整数 Group,表示有 Group 组测试数据。1≤Groutp≤5。
每组测试数据格式如下:
第一行:四个整数,xMe, yMe, xHome, yHome。 0≤xMe,yMe,xHome,yHome≤109。
接下来有三行,每行的格式是:四个整数 x1 y1 x2 y2, 表示有一个 teleport 的两个端点分别是:(x1,y1)、(x2,y2)。
数据保证:以上读入的 8 个点都不会相同。
输出格式 1778.out
共 R 行,每行一个整数,青蛙跳到家里的最短时间。
输入样例 1778.in
2
3 3 4 5
1000 1001 1000 1002
1000 1003 1000 1004
1000 1005 1000 1006
0 0 20 20
1 1 18 20
1000 1003 1000 1004
1000 1005 1000 1006
输出样例 1778.out
3
14
样例解释
样例一解释:
from (3,3) to (3,4), then to (3,5), and finally to (4,5).
样例二解释:
Make 2 jumps to get from (0,0) to (1,1), use the teleport to get to (18,20), and make 2 jumps to get to (20,20). This solution takes (2+10+2) = 14 seconds.
这道题目的意思很显然,就是要规划一下路径,使得从起点到终点的费用最小,其中费用定义如下。
路途中每走到
分布有 3 台穿越机,每台穿越机有两个点,可以从其中任意一个点进入,再穿越到另一点,花费为10。
对于一台穿越机,我们要么使用它 1 次,要么不使用它。不可能使用同一台穿越机多于 1 次,这是显然的。因为如果从点 A 穿越到点 B ,再穿越回点 A;或者从点 A 穿越到点 B,再走到点 A,再穿越到点 B,这两种情况都造成了浪费。不可能用两次,那么更加不可能用再多次了。
如此,便可以枚举使用穿越机的顺序。每一步,可以用三台穿越机中的任意一台,或者不用穿越机这四种情况,一共只有
但是要注意,穿越机的入口和出口是相对的。即使决定了使用某台穿越机,也要分开:从 A 到 B,或从 B 到 A 这两种情况讨论一下。
参考代码:
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long LL;
LL xMe, yMe, xHome, yHome;
LL x1[5], y1[5], x2[5], y2[5];
LL ans;
bool used[5];
inline LL dist(LL X1, LL Y1, LL X2, LL Y2) {
return abs(X1 - X2) + abs(Y1 - Y2);
}
void dfs(int k, LL lastx, LL lasty, LL sum) {
if (k == 3) {
ans = min(ans, sum + dist(lastx, lasty, xHome, yHome));
return ;
}
dfs(k + 1, lastx, lasty, sum);
for (int i = 0; i < 3; i++)
if (!used[i]) {
used[i] = true;
dfs(k + 1, x2[i], y2[i], sum + dist(lastx, lasty, x1[i], y1[i]) + 10);
dfs(k + 1, x1[i], y1[i], sum + dist(lastx, lasty, x2[i], y2[i]) + 10);
used[i] = false;
}
}
int main(void) {
freopen("1778.in", "r", stdin);
freopen("1778.out", "w", stdout);
int group;
scanf("%d", &group);
while (group--) {
scanf("%lld%lld%lld%lld", &xMe, &yMe, &xHome, &yHome);
ans = 1LL << 31;
for (int i = 0; i < 3; i++) scanf("%lld%lld%lld%lld", &x1[i], &y1[i], &x2[i], &y2[i]);
memset(used, false, sizeof used);
dfs(0, xMe, yMe, 0);
printf("%lld\n", ans);
}
return 0;
}