1 条题解

  • 0
    @ 2024-11-1 14:53:12

    此题难点在于相邻且高度相同的点不消耗体力,而普通的相邻点是要消耗体力的。所以我们考虑将高度相同且相邻的点合并成一个点。这样所有的点之前移动都消耗体力,就可以统一起来了。

    于是我们首先做一遍 bfs,将所有的相邻同高度格子选择一个统一的代表元(使用并查集维护)。

    合并好了之后,从大到小枚举权值,枚举邻点转移即可。

    时间复杂度 O(nm)O(nm)

    #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
    上传者