1 条题解
-
0
此题难点在于相邻且高度相同的点不消耗体力,而普通的相邻点是要消耗体力的。所以我们考虑将高度相同且相邻的点合并成一个点。这样所有的点之前移动都消耗体力,就可以统一起来了。
于是我们首先做一遍 bfs,将所有的相邻同高度格子选择一个统一的代表元(使用并查集维护)。
合并好了之后,从大到小枚举权值,枚举邻点转移即可。
时间复杂度 。
#include<bits/stdc++.h> using namespace std; const int maxn = 1010; int dx[] = {0,0,-1,1}, dy[] = {1,-1,0,0}; int n, m, T, f[maxn*maxn], g[maxn*maxn], h[maxn][maxn]; vector<pair<int,int>>ve[maxn*maxn]; int GF(int x) { return f[x] == x ? x : f[x] = GF(f[x]); } #define dot(x,y) (x-1)*m+y void mrg(int x, int y) { f[GF(x)] = GF(y); } int main() { cin >> T; while(T--) { cin >> n >> m; int ans = 0; for(int i = 1; i <= n * m; i++) ve[i].clear(), f[i] = i, g[i] = 0; for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++){ cin >> h[i][j]; ve[h[i][j]].push_back(make_pair(i,j)); } for(int i = n * m; i; i--) { for(auto z : ve[i]) { int x = z.first, y = z.second; for(int j = 0; j < 4; j++) { int nx = x + dx[j], ny = y + dy[j]; if(nx && ny && nx <= n && ny <= m && h[nx][ny] == h[x][y]){ mrg(dot(nx, ny), dot(x, y)); // 相邻且高度相同的点合并 } } } for(auto z : ve[i]) { int x = z.first, y = z.second, w = GF(dot(x,y)); for(int j = 0; j < 4; j++) { int nx = x + dx[j], ny = y + dy[j]; if(nx && ny && nx <= n && ny <= m && h[nx][ny] > h[x][y]){ g[w] = max(g[w], g[GF(dot(nx,ny))]+1); } } ans = max(ans, g[w]); } } cout << ans << endl; } }
信息
- ID
- 38
- 时间
- 2000ms
- 内存
- 512MiB
- 难度
- 8
- 标签
- (无)
- 递交数
- 101
- 已通过
- 17
- 上传者