图上每一个区域可以和四个方向相连接,采用二级制表示可以和哪些方向进行连接,1表示左,2表示上,4表示右,8表示下。
那么判断连接的时候可以用位运算,方便了代码的编写,提高了代码的效率。
剩下的就是并查集了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;
#define N 55
#define M 55
struct node
{
int rank;
int parent;
}t[N*M];
int n,m;
int map[N][M];
int vis[N*M];
int has[11]={3,6,9,12,10,5,7,11,13,14,15};
void make_set()
{
int i;
for(i=1;i<=n*m;i++)
{
t[i].rank=0;
t[i].parent=i;
}
}
int find_set(int x)
{
if(x!=t[x].parent)
return t[x].parent=find_set(t[x].parent);
else return x;
}
void union_set(int x,int y)
{
x=find_set(x);
y=find_set(y);
if(t[x].rank>t[y].rank)
{
t[y].parent=x;
}
else
{
t[x].parent=y;
if(t[x].rank==t[y].rank)t[y].rank++;
}
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
if(n<0||m<0)break;
memset(vis,0,sizeof vis);
memset(map,0,sizeof map);
int i,j,id,ans=0;
char c;
make_set();
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
cin>>c;
map[i][j]=has[c-'A'];
}
}
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
id=(i-1)*m+j;
if((map[i][j]&4)&&(map[i][j+1]&1))
union_set(id,id+1);//右
if((map[i][j]&8)&&(map[i+1][j]&2))
union_set(id,id+m);//下
}
}
for(i=1;i<=n*m;i++)
{
if(!vis[find_set(i)])
{
vis[find_set(i)]=1;
ans++;
}
}
printf("%d\n",ans);
}
return 0;
}
本文介绍了一种使用位运算结合并查集解决二维平面中区域连接问题的方法。通过将区域间的连接方向编码为二进制数,利用位运算快速判断连接状态,并通过并查集实现高效的数据管理。代码示例清晰展示了整个过程。
279

被折叠的 条评论
为什么被折叠?



