Gojou and Matrix Game
[Link](Problem - E - Codeforces)
题意
M M M和 G G G在一个 n × n n\times n n×n的二维矩阵中玩游戏,矩阵中每个位置元素值都不同,一共 n × n n\times n n×n局游戏, M M M每次从没有开局过的位置开始游戏,两个人依次加上选取位置上的值,但要满足当前选取的位置与上一次选取的位置的曼哈顿距离大于 k k k(除第一个人外),每局游戏一共选取 1 0 100 10^{100} 10100次,请你输出 M M M从每个位置开局的结果。
思路
假设 M M M选了 x x x下一次 G G G选了 y y y,且 x > y x >y x>y则 M M M必胜,因为 M M M在 G G G选完后还可以一直选 x x x,会一直扩大自己的优势,所以 M M M从值最大的格子开局必胜,设 f [ i ] [ j ] : ( i , j ) 这 个 格 子 必 胜 还 是 必 败 f[i][j]:(i,j)这个格子必胜还是必败 f[i][j]:(i,j)这个格子必胜还是必败。
因为每个格子只会和权值比他大的格子产生关系所以我们将所有的格子按照权值从大到小排序,对于第 k k k个格子 ( x 1 , y 1 ) (x_1,y_1) (x1,y1)来说如果它能到某个必胜的格子则必败,因为下一个人就可以选那个格子了。因此我们需要判断第 k k k个格子前面所有必胜的格子是否曼哈顿距离大于 k k k,暴力存取的话复杂度为 O ( n 4 ) O(n^4) O(n4)就 T T T了。
考虑一下数学式子,对于 ( x 1 , y 1 ) 和 ( x 2 , y 2 ) (x_1,y_1)和(x_2,y_2) (x1,y1)和(x2,y2)我们要检察 a b s ( x 1 − x 2 ) + a b s ( y 1 − y 2 ) > k abs(x_1-x_2)+abs(y_1-y_2)>k abs(x1−x2)+abs(y1−y2)>k,有四种情况:
-
左边 > 0 >0 >0,右边 > 0 >0 >0 即 x 1 − x 2 + y 1 − y 2 > k → ( x 1 + y 1 ) − ( x 2 + y 2 ) > k x_1-x_2+y_1-y_2>k\to(x_1+y_1)-(x_2+y_2)>k x1−x2+y1−y2>k→(x1+y1)−(x2+y2)>k
-
左边 < 0 <0 <0,右边 < 0 <0 <0 即 x 2 − x 1 + y 2 − y 1 > k → − ( ( x 1 + y 1 ) − ( x 2 + y 2 ) ) > k x_2-x_1+y_2-y_1>k\to-((x_1+y_1)-(x_2+y_2))>k x2−x1+y2−y1>k→−((x1+y1)−(x2+y2))>k
-
左边 > 0 >0 >0,右边 < 0 <0 <0 即 x 1 − x 2 + y 2 − y 1 > k → ( x 1 − y 1 ) − ( x 2 + y 2 ) > k x_1-x_2+y_2-y_1>k\to(x_1-y_1)-(x_2+y_2)>k x1−x2+y2−y1>k→(x1−y1)−(x2+y2)>k
-
左边 < 0 <0 <0,右边 < 0 <0 <0 即 x 2 − x 1 + y 1 − y 2 > k → − ( ( x 1 − y 1 ) − ( x 2 + y 2 ) ) > k x_2-x_1+y_1-y_2>k\to-((x_1-y_1)-(x_2+y_2))>k x2−x1+y1−y2>k→−((x1−y1)−(x2+y2))>k
发现 a b s ( x 1 − x 2 ) + a b s ( y 1 − y 2 ) > k ⇔ m a x ( a b s ( ( x 1 + y 1 ) − ( x 2 + y 2 ) ) , a b s ( ( x 1 − y 1 ) − ( x 2 + y 2 ) ) ) > k abs(x_1-x_2)+abs(y_1-y_2)>k\Leftrightarrow max(abs((x_1+y_1)-(x_2+y_2)),abs((x_1-y_1)-(x_2+y_2)))>k abs(x1−x2)+abs(y1−y2)>k⇔max(abs((x1+y1)−(x2+y2)),abs((x1−y1)−(x2+y2)))>k,因此我们维护一下合法的 x + y x+y x+y和 x − y x-y x−y的最大最小值即可复杂度 O ( n 2 ) O(n^2) O(n2)。
Code
#include <bits/stdc++.h>
#define x first
#define y second
#define debug(x) cout<<#x<<":"<<x<<endl;
using namespace std;
typedef long double ld;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef unsigned long long ULL;
const int N = 1e5 + 10, M = 2 * N, INF = 0x3f3f3f3f, mod = 1e9 + 7;
const double eps = 1e-8, pi = acos(-1), inf = 1e20;
int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
int h[N], e[M], ne[M], w[M], idx;
void add(int a, int b, int v = 0) {
e[idx] = b, w[idx] = v, ne[idx] = h[a], h[a] = idx ++;
}
int n, m, k;
int a[N];
void solve() {
cin >> n >> k;
vector<array<int, 5>> g(n * n);
vector<vector<bool>> f(n + 1, vector<bool>(n + 1, false));
for (int i = 1; i <= n; i ++)
for (int j = 1; j <= n; j ++) {
int x; cin >> x;
g.push_back({x, i, j, i + j, i - j});
}
sort(g.begin(), g.end(), [&](array<int, 5> a, array<int, 5> b) {
return a[0] > b[0];
});
vector<int> c(4);
function<bool(int , int )> check = [&](int x, int y) {
if (abs(x + y - c[0]) > k || abs(x + y - c[1]) > k || abs(x - y - c[2]) > k || abs(x - y - c[3]) > k) return false;
return true;
};
f[g[0][1]][g[0][2]] = true; c[0] = c[1] = g[0][3], c[2] = c[3] = g[0][4];
for (int i = 1; i < n * n; i ++) {
if (check(g[i][1], g[i][2])) {
f[g[i][1]][g[i][2]] = true;
c[0] = max(c[0], g[i][3]);
c[1] = min(c[1], g[i][3]);
c[2] = min(c[2], g[i][4]);
c[3] = max(c[3], g[i][4]);
}
}
for (int i = 1; i <= n; i ++) {
for (int j = 1; j <= n; j ++)
cout << (f[i][j] ? 'M' : 'G');
cout << '\n';
}
}
int main() {
ios::sync_with_stdio(false), cin.tie(0);
int T = 1;
// cin >> T;
while (T -- ) {
solve();
}
return 0;
}