https://vjudge.net/problem/UVA-572
给你一块地图 ,其中' @ '代表探测到有油的地方, 而' * '则是代表没有油的地方。 现在题目给出了油田的定义,所有连在一起的' @ ' 代表一个油田, 而连在一起的定义是有公共点或公共边。 而题目的要求是输出给你一张地图上的油田的个数。 思路: 这个题没什么特别的思路, 就是找到一个初始的' @ ', 然后遍历一遍,把与他属于同一个油田的都标记了,或者清楚。
思路:这个题目一般的方法就是深度遍历。
但是我这里用的是并查集。用了两个小时,需要注意的地方
1. 如果使用%c输入字符有问题,估计是处理了回车之类的,这里适用gets或者流来输入好点
2 两个都是@的时候,如何表示左右、上下还有对角线,注意不要遗漏。
#include<iostream>
#include<cstdio>
#include<set>
#include<vector>
using namespace std;
#define nMax 105
char info[nMax][nMax];
vector<int> parent;
vector<int> iRank;
int xx[8]={-1,1,0,0,-1,1,1,-1};
int yy[8]={0,0,-1,1,-1,1,-1,1};
set<int> iset;
int main()
{
int root(int p);
void uni(int p, int q);
int kcase=1;
int N,M;
int len;
while(scanf("%d %d",&N,&M)==2&&M&&N)
{
len=N*M;
parent.resize(len);
iRank.resize(len);
for(int i=0;i<N;i++)
{
for(int j=0;j<M;j++)
{
//scanf("%c",&info[i][j]);
cin>>info[i][j];
parent[i*M+j]=-1;
if(info[i][j]=='@')
{
parent[i*M+j]=i*M+j;
iRank[i*M+j]=1;
}
}
}
for(int i=0;i<N;i++)
{
for(int j=0;j<M;j++)
{
for(int k=0;k<8;k++)
{
int newx=i+xx[k];
int newy=j+yy[k];
if(newx>=0&&newx<N&&newy>=0&&newy<M)
if(info[i][j]=='@'&&info[newx][newy]=='@')
uni(i*M+j,newx*M+newy);
}
}
}
iset.clear();
for(int i=0;i<len;i++)
{
if(parent[i]>-1&&!iset.count(root(i)))
{
iset.insert(root(parent[i]));
}
//cout<<parent[i];
//if((i+1)%M==0) cout<<endl;
}
cout<<iset.size()<<endl;
}
return 0;
}
int root(int p)
{
if(p != parent[p])
{
parent[p] = root(parent[p]);
}
return parent[p];
}
void uni(int p, int q)
{
int proot = root(p);
int qroot = root(q);
if(proot == qroot) return ;
if(iRank[proot] > iRank[qroot])
{
parent[qroot] = proot;
}
else
{
if(iRank[proot] = iRank[qroot])
{
iRank[qroot]++;
}
parent[proot] = qroot;
}
}