NOI Online #3 入门组 第二题:观星

NOI Online #3 入门组 第二题:观星

  • 题目
  • 解析
  • 代码

题目

题目传送门

解析

BFS和DFS的简单题目,在这我只讲BFS。

我们先找到一个 *,然后对其进行 BFS,并将所有访问过的 * 标记为 .,在进行 BFS 的同时记录下目前的 * 数量。

当一次 BFS 结束后,我们将统计的数量放入之前开好的桶中,即将 h r e s + 1 h_{res}+1 hres+1

如果此时 h r e s h_{res} hres 0 0 0,则将星系数量加上 1 1 1 并更新此时最大的星系,因为只有 h r e s h_{res} hres 改变了,所以只需要将 h r e s h_{res} hres m a x max max 比较。

结束后再找到一个没有被访问过的 *,然后重复上述过程,直到所有 * 被访问。

代码

#include
using namespace std;
char g[2010][2010];
int n,m,h[20000010],maxn,tots,cnt1,cnt2;
struct node //结构体
{
     
	int x,y;
};
queue<node> q;
int dx[8]={
     0,0,-1,1,1,-1,-1,1};
int dy[8]={
     1,-1,0,0,1,1,-1,-1};
void bfs(int x,int y) //宽搜
{
     
	node no;
	no.x=x;
	no.y=y;
	q.push(no);
	int res=1;
	g[no.x][no.y]='.';
	while(!q.empty())
	{
     
		node fr=q.front();
		for(int i=0;i<8;i++)
		{
     
			if(g[fr.x+dx[i]][fr.y+dy[i]]=='*')
			{
     
				no.x=fr.x+dx[i];no.y=fr.y+dy[i];
				q.push(no);
				g[fr.x+dx[i]][fr.y+dy[i]]='.';
				res++;
			}
		}
		q.pop();
	}
	if(h[res]==0) cnt2++;
	h[res]++; //放入桶中
	maxn=max(maxn,h[res]*res);//更新Maxn
	cnt1+=res; //总数++
}
int main()
{
     
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{
     
		for(int j=1;j<=m;j++)
		{
     
			cin>>g[i][j];
			if(g[i][j]=='*') tots++;
		}
	}
	while(cnt1<tots)
	{
     
		int Dx,Dy;
		for(int i=1;i<=n;i++)
		{
     
			for(int j=1;j<=m;j++)
			{
     
				if(g[i][j]=='*')
				{
     
					Dx=i;
					Dy=j;
					bfs(Dx,Dy);
				}
			}
		}
	} 
	printf("%d %d",cnt2,maxn);//输出
	return 0;
}

还有DFS写法,其实DFS是非常好想的,就是上、下、左、右、左上、右上、左下、右下这四个方位搜索,找到一个标记一个,记住DFS的时候要在未曾遍历过的点上搜索

#include
using namespace std;
const int Maxn=10010;
const int Maxm=100010;
char Mp[Maxn][Maxn];
int n,m;
bool vis[Maxn][Maxn];
int cnt=0,tmp=0,ans=-0x3f3f3f3f; //初始化+定义
void dfs(int x,int y) // 暴力DFS
{
     
	if(x<1 || x>n || y<1 || y>m || Mp[x][y]=='.' || vis[x][y] || Count[x][y]) return ; // return 的原因
	vis[x][y]=true; //将它设为经过了
	tmp++;
	dfs(x+1,y);
	dfs(x,y+1);
	dfs(x-1,y);
	dfs(x,y-1);
	dfs(x-1,y-1);
	dfs(x-1,y+1);
	dfs(x+1,y-1);
	dfs(x+1,y+1);
	//这上头是八个DFS的方位
	vis[x][y]=false; //回溯
}
struct St{
     
	int Score;
}Ans[Maxm];
int main()
{
     
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{
     
		for(int j=1;j<=m;j++)
		{
     
			cin>>Mp[i][j]; //输入地图
		}
	}
	for(int i=1;i<=n;i++)
	{
     
		for(int j=1;j<=m;j++)
		{
     
			if(Mp[i][j]=='*' && !vis[i][j]) //要从没有遍历过的点开始遍历
			{
     
				tmp=0;
				dfs(i,j);
				Ans[tmp].Score++;
				ans=max(tmp,ans); 
			}
		}
	}
	int maxn=-0x3f3f3f3f;
	for(int i=1;i<=ans;i++)
	{
     
		if(Ans[i].Score!=0) //如果这个星座数的星系有的话
		{
     
			cnt++; //星系个数++
			maxn=max(maxn,i*Ans[i].Score); // Maxn更新
		}
	}
	printf("%d %d\n",cnt,maxn);
	return 0;
}

你可能感兴趣的:(C++,Noi的题目,C++题解)