This commit is contained in:
1 parent
b93c6ac8a4
commit
16f444ee63
2 files changed
+185
No files matched your search
@@ -0,0 +1,101 @@
|
|||||||
|
# CF1681E Labyrinth Adventures
|
||||||
|
|
||||||
|
## 题目描述
|
||||||
|
|
||||||
|
有一个 $n\times n$ 的方格图,坐标编号类似平面直角坐标系,左下角为 $(1, 1)$。
|
||||||
|
|
||||||
|
这个方格图被分成了 $n$ 层,左下角 $(1, 1)$ 为第一层,随后每层都向外拓展一圈,如下图就是 $n=5$ 的时候的情况:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
层与层之间有墙隔开,但每层都有两个门,分别分布在该层顶部和右侧,门是双向的。
|
||||||
|
|
||||||
|
现在给出这些门的坐标,有 $m$ 次询问,每次给定两个坐标 $(x_1, y_1)$ 和 $(x_2,y_2)$,请你回答两点之间的最短路。
|
||||||
|
|
||||||
|
## 输入格式
|
||||||
|
|
||||||
|
第一行输入 $n$。
|
||||||
|
|
||||||
|
接下来的 $n-1$ 行中,每行有四个整数 $d_{1,x}, d_{1,y}, d_{2,x}, d_{2,y}$,表示第 $i$ 层的两个门的坐标。前两个表示顶部门坐标,后两个表示右侧门坐标。
|
||||||
|
|
||||||
|
之后一行输入 $m$。
|
||||||
|
|
||||||
|
接下来的 $m$ 行中,每行有四个整数 $x_1,y_1,x_2,y_2$,表示每次询问中起点与终点的坐标。
|
||||||
|
|
||||||
|
## 输出格式
|
||||||
|
|
||||||
|
对每次询问,输出一行一个整数,表示两点之间的最短路长度。**长度的定义是移动的步数。**
|
||||||
|
|
||||||
|
## 输入输出样例 #1
|
||||||
|
|
||||||
|
### 输入 #1
|
||||||
|
|
||||||
|
```
|
||||||
|
2
|
||||||
|
1 1 1 1
|
||||||
|
10
|
||||||
|
1 1 1 1
|
||||||
|
1 1 1 2
|
||||||
|
1 1 2 1
|
||||||
|
1 1 2 2
|
||||||
|
1 2 1 2
|
||||||
|
1 2 2 1
|
||||||
|
1 2 2 2
|
||||||
|
2 1 2 1
|
||||||
|
2 1 2 2
|
||||||
|
2 2 2 2
|
||||||
|
```
|
||||||
|
|
||||||
|
### 输出 #1
|
||||||
|
|
||||||
|
```
|
||||||
|
0
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
0
|
||||||
|
2
|
||||||
|
1
|
||||||
|
0
|
||||||
|
1
|
||||||
|
0
|
||||||
|
```
|
||||||
|
|
||||||
|
## 输入输出样例 #2
|
||||||
|
|
||||||
|
### 输入 #2
|
||||||
|
|
||||||
|
```
|
||||||
|
4
|
||||||
|
1 1 1 1
|
||||||
|
2 1 2 2
|
||||||
|
3 2 1 3
|
||||||
|
5
|
||||||
|
2 4 4 3
|
||||||
|
4 4 3 3
|
||||||
|
1 2 3 3
|
||||||
|
2 2 4 4
|
||||||
|
1 4 2 3
|
||||||
|
```
|
||||||
|
|
||||||
|
### 输出 #2
|
||||||
|
|
||||||
|
```
|
||||||
|
3
|
||||||
|
4
|
||||||
|
3
|
||||||
|
6
|
||||||
|
2
|
||||||
|
```
|
||||||
|
|
||||||
|
## 说明/提示
|
||||||
|
|
||||||
|
#### 样例解释
|
||||||
|
|
||||||
|
下图是样例二的网格图,红色的是门。
|
||||||
|
|
||||||
|

|
||||||
|
#### 数据范围
|
||||||
|
$1 \le n \le 10^5$;
|
||||||
|
|
||||||
|
$2 \le m \le 2 \times 10^5$。
|
||||||
+84
@@ -0,0 +1,84 @@
|
|||||||
|
#include <bits/stdc++.h>
|
||||||
|
#define int long long
|
||||||
|
using namespace std;
|
||||||
|
typedef pair<int, int> pii;
|
||||||
|
const int INF = 1e18;
|
||||||
|
int n;
|
||||||
|
pair<pii, pii> doors[100005];
|
||||||
|
int m;
|
||||||
|
int dp[100005][20][2][2];
|
||||||
|
signed main()
|
||||||
|
{
|
||||||
|
scanf("%lld", &n);
|
||||||
|
for (int i = 1; i < n; ++i)
|
||||||
|
{
|
||||||
|
int xx1, yy1, xx2, yy2;
|
||||||
|
scanf("%lld%lld%lld%lld", &xx1, &yy1, &xx2, &yy2);
|
||||||
|
doors[i] = {{xx1, yy1}, {xx2, yy2}};
|
||||||
|
}
|
||||||
|
for(int i = 2; i < n; ++i) {
|
||||||
|
for (int a = 0; a < 2; ++a) {
|
||||||
|
pii out;
|
||||||
|
if (a == 0) out = {doors[i - 1].first.first + 1, doors[i - 1].first.second};
|
||||||
|
else out = {doors[i - 1].second.first, doors[i - 1].second.second + 1};
|
||||||
|
for (int b = 0; b < 2; ++b) {
|
||||||
|
pii dest = (b == 0) ? doors[i].first : doors[i].second;
|
||||||
|
dp[i - 1][0][a][b] = 1 + abs(out.first - dest.first) + abs(out.second - dest.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(int i = 1; i <= 19; ++i) {
|
||||||
|
for(int j = 1; j + (1 << i) <= n - 1; ++j) {
|
||||||
|
dp[j][i][0][0] = min(dp[j][i - 1][0][0] + dp[j + (1 << (i - 1))][i - 1][0][0], dp[j][i - 1][0][1] + dp[j + (1 << (i - 1))][i - 1][1][0]);
|
||||||
|
dp[j][i][0][1] = min(dp[j][i - 1][0][0] + dp[j + (1 << (i - 1))][i - 1][0][1], dp[j][i - 1][0][1] + dp[j + (1 << (i - 1))][i - 1][1][1]);
|
||||||
|
dp[j][i][1][0] = min(dp[j][i - 1][1][0] + dp[j + (1 << (i - 1))][i - 1][0][0], dp[j][i - 1][1][1] + dp[j + (1 << (i - 1))][i - 1][1][0]);
|
||||||
|
dp[j][i][1][1] = min(dp[j][i - 1][1][0] + dp[j + (1 << (i - 1))][i - 1][0][1], dp[j][i - 1][1][1] + dp[j + (1 << (i - 1))][i - 1][1][1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scanf("%lld", &m);
|
||||||
|
while (m--)
|
||||||
|
{
|
||||||
|
pii s, e;
|
||||||
|
scanf("%lld%lld%lld%lld", &s.first, &s.second, &e.first, &e.second);
|
||||||
|
int sc = max(s.first, s.second);
|
||||||
|
int ec = max(e.first, e.second);
|
||||||
|
if(sc > ec) swap(sc, ec), swap(s, e);
|
||||||
|
else if(sc == ec) {
|
||||||
|
printf("%lld\n", abs(s.first - e.first) + abs(s.second - e.second));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ec--;
|
||||||
|
int ds[2], de[2];
|
||||||
|
ds[0] = abs(doors[sc].first.first - s.first) + abs(doors[sc].first.second - s.second);
|
||||||
|
ds[1] = abs(doors[sc].second.first - s.first) + abs(doors[sc].second.second - s.second);
|
||||||
|
for (int b = 0; b < 2; ++b) {
|
||||||
|
pii out;
|
||||||
|
if (b == 0) out = {doors[ec].first.first + 1, doors[ec].first.second};
|
||||||
|
else out = {doors[ec].second.first, doors[ec].second.second + 1};
|
||||||
|
de[b] = 1 + abs(out.first - e.first) + abs(out.second - e.second);
|
||||||
|
}
|
||||||
|
int M[2][2] = {{0, INF}, {INF, 0}};
|
||||||
|
int now = sc;
|
||||||
|
int len = ec - sc;
|
||||||
|
for (int i = 19; i >= 0; --i) {
|
||||||
|
if (len >= (1 << i)) {
|
||||||
|
int tmp[2][2];
|
||||||
|
for (int a = 0; a < 2; ++a)
|
||||||
|
for (int b = 0; b < 2; ++b) {
|
||||||
|
tmp[a][b] = INF;
|
||||||
|
for (int k = 0; k < 2; ++k)
|
||||||
|
tmp[a][b] = min(tmp[a][b], M[a][k] + dp[now][i][k][b]);
|
||||||
|
}
|
||||||
|
memcpy(M, tmp, sizeof(M));
|
||||||
|
now += (1 << i);
|
||||||
|
len -= (1 << i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int ans = INF;
|
||||||
|
for (int a = 0; a < 2; ++a)
|
||||||
|
for (int b = 0; b < 2; ++b)
|
||||||
|
ans = min(ans, ds[a] + M[a][b] + de[b]);
|
||||||
|
printf("%lld\n", ans);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in new issue
Block a user