[JOISC 2021] Navigation 2

Sol

(题面太长,所以无了)

这题是一道通信题,需要构造方案。

观察该图形的染色(字母染色):

[A][B][C][A][B][C]
[D][E][F][D][E][F]
[G][H][I][G][H][I]
[A][B][C][A][B][C]
[D][E][F][D][E][F]
[G][H][I][G][H][I]

发现了什么?任意取一个 (3 imes 3) 的矩形,每个字母仅出现一次。这在接下来的方法中十分有用。

为了保证关于每一个 目标点 信息能够实时获取,我们就采用上面的方式来实现。当然,对于不同的矩形,处在最左上角的字母是不一样的,所以我们需要选取一个 基准点,由上面染色方法的规律性,找到基准点就能还原出整个矩形中的东西。

所以,在下面的矩形中:

[1][2][3]
[=][+][4]
[7][6][5]

我们令 + 为基准点,1~7 中存关于目标点 1 到 7 的信息,= 的信息暂时不管。格子在标号(原题:插旗子)的时候,基准点要与众不同,我们使用 最大的数字 (L) 来表示基准点。对于 1 到 7,想一想如何分配剩下的数字。

举特例,我们要让 [1] 信息要能 准确、连续 地引导 Bruno 前往终点 并且在 终点停下。这里,如果终点在以 [1] 的位置为中心的九格以内,使用 (9) 个数字表示终点的位置,这里的位置表示相对于 [1] 的位置。例如

(1)(2)(3)
(8)(9)(4)
(7)(6)(5)

每个数字表示了相对于 [1] 的位置。例如这里 数字1 代表 1 号目标点在 [1] 的左上格,数字9 代表就在 [1] 的位置

反之,使用 (4) 个数字表示以 [1] 的位置为基准,到终点 坐标差 (geq 2) 的方向 (X) 走,也就是说,只要 Bruno 落在 [1] 的九格范围之内(能看到这个 [1]),都往 (X) 方向走。例如

    (13)
(11)    (10)
    (12)

数字10 表示往右(东)走,数字13 表示往上(北)走。

举例子:对于地图上终点分布如下的图

[ ][ ][ ][ ][ ]
[ ][1][ ][ ][ ]
[ ][ ][ ][ ][ ]
[ ][ ][ ][2][ ]
[ ][ ][ ][ ][ ]

我们可以这样染色

[1][2][3][1][2]
[=][+][4][=][+]
[7][6][5][7][6]
[1][2][3][1][2]
[=][+][4][=][+]

我们可以这样标号

( 5)(12)( /)(11)(12)
( /)( L)( /)( /)( L)
( /)( /)( /)( /)( /)
(13)(10)( /)(11)( 8)
( /)( L)( /)( /)( L)

符号 / 表示任意填数字。

下面简略说明这样的标识一定能够找到终点。首先,对于格子的指示其实是有延时的,比如下列情况(x 表示 Bruno)

[ ][ ][x]
[ ][1][ ]
[ ][ ][ ]

假设 [1] 告诉 Bruno 要往上走,那只是相对其而言 (Delta >1),但对于 (x) 而言 (Delta ge 1)。即使这样,往上走一步也不会导致 走过线,因为此时已经超出 [1] 的指示范围了。

如果直接指向终点,显然没什么问题,对着终点走或者停下来即可。

通过以上的方法,我们数一数发现 (L=9+4+1=14),可以获得 75 分。

注意到我们调整基准点坐标模 3 意义下的位置,我们可以避免掉终点在正中间的情况,这样可以做到 (L=13),获得 85 分。

但是我们不太容易再次去掉一个终点在某一格的情况,这样可能会出现无法调整的情况。注意,我们还有一个格子 [=] 没有使用。结合题目中 每轮场景只会调用一次,能得到一个出错率在 (10^{-4}) 以下的方法:[=] 表示将每个小矩形染色旋转一定角度,例如:

[1][2][3]
[=][+][4]
[7][6][5]

[=][1][2]
[7][+][3]
[6][5][4]

我们可以令 [=] 的值也为 (L),这样每个矩形内将会有两个 (L),以此判断旋转了多少度。旋转结合平移,仅记录 7 个终点位置、避免掉 2 个位置,对于绝大多数情况下都不会出问题。这样可以 (L=12)。多调整几次就能通过此题。

Code

// Anna
#include "Anna.h"
#include <bits/stdc++.h>
using std::vector;
const int N = 105;
namespace {
int n, r[8], c[8], a[N][N], col[N][N];
int dx[8] = {-1, -1, 0, 1, 1, 1, 0, -1};
int dy[8] = {0, -1, -1, -1, 0, 1, 1, 1};
}
bool In(int x, int y) { return x >= 0 && x < n && y >= 0 && y < n; }
bool test(int s, int px, int py) {
	int ok = 1;
	memset(a, 0, sizeof a); memset(col, 0, sizeof col);
	for (int i = -1; i <= n; i++)
		for (int j = -1; j <= n; j++)
			if ((i + 3) % 3 == px && (j + 3) % 3 == py) {
				if (In(i, j)) a[i][j] = 12;
				if (In(i + dx[s], j + dy[s])) a[i + dx[s]][j + dy[s]] = 12;
				for (int k = 1; k < 8; k++) {
					int x = i + dx[(s + k) % 8], y = j + dy[(s + k) % 8];
					if (!In(x, y)) continue;
					col[x][y] = k;
					if (x - r[k] > 1) a[x][y] = 8;
					else if (r[k] - x > 1) a[x][y] = 9;
					else if (y - c[k] > 1) a[x][y] = 10;
					else if (c[k] - y > 1) a[x][y] = 11;
					else if (x - 1 == r[k] && y - 1 == c[k]) a[x][y] = 1;
					else if (x - 1 == r[k] && y == c[k]) a[x][y] = 2;
					else if (x - 1 == r[k] && y + 1 == c[k]) a[x][y] = 3;
					else if (x == r[k] && y - 1 == c[k]) a[x][y] = 4;
					else if (x == r[k] && y + 1 == c[k]) a[x][y] = 5;
					else if (x + 1 == r[k] && y - 1 == c[k]) a[x][y] = 6;
					else if (x + 1 == r[k] && y + 1 == c[k]) a[x][y] = 7;
					else { ok = 0; a[x][y] = 9; }
				}
			}
	return ok;
}
void Anna(int n, int k, vector<int> r, vector<int> c) {
	::n = n;
	for (int i = 0; i < k; i++)
		::r[i + 1] = r[i], ::c[i + 1] = c[i];
	for (int s = 1; s < 5; s++)
		for (int i = 0; i < 3; i++)
			for (int j = 0; j < 3; j++)
				if (test(s, i, j)) goto nice;
	nice:
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++)
			SetFlag(i, j, a[i][j]);
}
// Bruno
#include "Bruno.h"
#include <bits/stdc++.h>
using std::vector;
namespace {
int dx[9] = {-1, -1, 0, 1, 1, 1, 0, -1, 0};
int dy[9] = {0, -1, -1, -1, 0, 1, 1, 1, 0};
int a[3][3];
}
vector<int> Bruno(int k, vector<int> value) {
	vector<int> ret(7);
	for (int i = 0; i < 9; i++)
		a[i / 3][i % 3] = value[i];
	for (int p = 0; p < 9; p++)
		for (int s = 1; s < 5; s++)
			if (a[1 + dx[p]][1 + dy[p]] == 12 && a[(4 + dx[p] + dx[s]) % 3][(4 + dy[p] + dy[s]) % 3] == 12) {
				for (int i = 1; i < 8; i++) {
					int x = (4 + dx[p] + dx[(s + i) % 8]) % 3, y = (4 + dy[p] + dy[(s + i) % 8]) % 3;
					if (a[x][y] == 8) ret[i - 1] = 3;
					else if (a[x][y] == 9) ret[i - 1] = 2;
					else if (a[x][y] == 10) ret[i - 1] = 1;
					else if (a[x][y] == 11) ret[i - 1] = 0;
					else {
						int locx, locy;
						if (a[x][y] == 1) locx = x - 1, locy = y - 1;
						else if (a[x][y] == 2) locx = x - 1, locy = y;
						else if (a[x][y] == 3) locx = x - 1, locy = y + 1;
						else if (a[x][y] == 4) locx = x, locy = y - 1;
						else if (a[x][y] == 5) locx = x, locy = y + 1;
						else if (a[x][y] == 6) locx = x + 1, locy = y - 1;
						else if (a[x][y] == 7) locx = x + 1, locy = y + 1;
						if (locy > 1) ret[i - 1] = 0;
						else if (locy < 1) ret[i - 1] = 1;
						else if (locx > 1) ret[i - 1] = 2;
						else if (locx < 1) ret[i - 1] = 3;
						else ret[i - 1] = 4;
					}
				}
				goto nice;
			}
	nice:
	return ret;
}
原文地址:https://www.cnblogs.com/ac-evil/p/14585908.html