历时1周的学习和总结,今天将结束并查集的学习,明天将会开启新的篇章。学习并解决关于树的相关问题和内容。
问题描述
鸡哥正在参与一场精彩的冒险活动,这个活动的场地是一个巨大的迷宫,由 N×M 个不同的房间组成,每个房间都恰好有一个彩色大珠子。每个房间都有一个独特的魔法级别,魔法级别由一个整数表示,不同的房间魔法级别也不同。
每个珠子都被施加了一个魔法,它们会自动移动。珠子的移动规则如下:
- 如果当前房间的魔法级别比所有相邻房间(最多有 8 个)的魔法级别都小,那么珠子就会停在这个房间。
- 否则,珠子会移动到魔法级别最小的相邻房间。
鸡哥对这个迷宫非常好奇,他想知道最后每个房间里会有多少珠子。作为他的朋友,你能帮他解答这个问题吗?
输入格式
输入的第一行包含两个整数 N 和 M(1≤N,M≤200)。
接下来的 N 行,每行包含 M个整数,代表每个房间的魔法级别。魔法级别的范围在 0∼105 之间,且每个房间的魔法级别都是独特的。
输出格式
输出 N行,每行包含 M个整数。第 i 行的第 j 个数应该表示最后房间 (i,j) 里的珠子数量。
输入案例:
3 3
1 2 3
4 5 6
7 8 9
输出案例:
9 0 0
0 0 0
0 0 0
代码部分:
#include<bits/stdc++.h>
using namespace std;
#define c(i,j) (i)*m+j
int m,n,b[100005],a[100005];
int find(int x){
return x==b[x]?x:(b[x]=find(b[x]));
}
int main(){
cin>>n>>m;
for (int i=0;i<n;i++){
for (int j=0;j<m;j++){
b[c(i,j)]=c(i,j);
cin>>a[c(i,j)];
}
}
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{int h=c(i,j);
for(int x=i-1;x<=i+1;x++)
for(int y=j-1;y<=j+1;y++)
{
if(x<0||x>=n||y<0||y>=m)continue;
if(a[c(x,y)]<a[h])h=c(x,y);
}
b[c(i,j)]=find(b[h]);
}
memset(a,0,sizeof(a));
for (int i=0;i<n*m;i++){
a[find(i)]++;
}
for (int i=0;i<n*m;i++){
cout<<a[i]<<((i+1)%m==0?'\n':' ');
}
return 0;
}
这道题的关键是在
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
int h = c(i,j); // 当前房间的一维索引
// 检查 8 个相邻房间(包括自己)
for (int x = i-1; x <= i+1; x++) {
for (int y = j-1; y <= j+1; y++) {
if (x < 0 || x >= n || y < 0 || y >= m) continue; // 越界跳过
if (a[c(x,y)] < a[h]) h = c(x,y); // 找到魔法级别最小的相邻房间
}
}
b[c(i,j)] = find(b[h]); // 合并到最小魔法级别的房间
}
}
遍历每个房间
(i,j)
:检查其 8 邻域(包括自身)的魔法级别。
找到 魔法级别最小的房间
h
。将当前房间的父节点指向
h
的根节点(find(b[h])
),表示珠子会移动到h
。
理解了这个部分就可以更好地理解了这段代码所表示的相关内容。
好了这部分分享就到这里,希望能对大家有所帮助,后续也将继续进行相关内容的分享和学习,希望大家可以多多关注,后续再见