题解:P9698 [GDCPC 2023] Path Planning
BlackMagician · · 题解
提供一个
因为题目保证了
这个判断并不困难。对于某个数字
我们不可能暴力的对每个点对应的这两个矩形内的所有点都做一遍标记,这里介绍一个可以优化的思路:以右上方的矩形为例,这个矩形的起点是
参考代码如下。
#include <bits/stdc++.h>
#define ll long long
#define mod 1000000007
#define eps 1e−7
using namespace std;
const double PI = acos(−1);
const int N = 1e6 + 10;
int dx[] = {0, 1, 0, −1};
int dy[] = {−1, 0, 1, 0};
int n, m;
void dfs1(int x, int y, vector<vector<int>> &vis)
{
if (x < 1 || x > n || y < 1 || y > m)
return;
vis[x][y] = true;
for (int i = 2; i <= 3; i++)
{
int tx = x + dx[i], ty = y + dy[i];
if (tx < 1 || ty < 1 || tx > n || ty > m || vis[tx][ty])
continue;
dfs1(tx, ty, vis);
}
}
void dfs2(int x, int y, vector<vector<int>> &vis)
{
if (x < 1 || x > n || y < 1 || y > m)
return;
vis[x][y] = true;
for (int i = 0; i <= 1; i++)
{
int tx = x + dx[i], ty = y + dy[i];
if (tx < 1 || ty < 1 || tx > n || ty > m || vis[tx][ty])
continue;
dfs2(tx, ty, vis);
}
}
void solve()
{
cin >> n >> m;
vector a(n + 10, vector<int>(m + 10, 0));
vector vis = a;
vector<pair<int, int>> c((n + 10) * (m + 10));
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
cin >> a[i][j], c[a[i][j]] = {i, j};
int res = 0;
for (int i = 0; i < n * m; i++)
{
if (!vis[c[i].first][c[i].second])
{
res++;
auto [x, y] = c[i];
vis[x][y] = true;
dfs1(x − 1, y + 1, vis);
dfs2(x + 1, y − 1, vis);
}
else
break;
}
cout << res << "\n";
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int _ = 1;
cin >> _;
while (_−−)
{
solve();
}
return 0;
}
/*
*/