[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 \times 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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章