P1141 01迷宫

这题数据有点高级啊(这么高级的数据能不能把它变成黄题呢?不然显得我很垃圾(虽然是事实))

思路

联通块,把周围四格与自己不同的联通起来,看成一个大块,知道要的坐标属于哪个大块并数出大块有多少个点就行了

 

我的第一个想法是先预处理出联通块,然后直接暴力搜索,需要哪个坐标就去搜大块有几个点(想着橙题,随便做都能AC。。

(70分。。

#include <bits/stdc++.h>
using namespace std;
int a[1005][1005];
int b[1005][1005];
bool c[1005][1005];
int n,m;
void build(int x,int y,int k)
{
	if(x>n || x==0) return; if(y>n || y==0) return ;
	b[x][y]=k;
	if(a[x+1][y]!=a[x][y] && !b[x+1][y]) build(x+1,y,k);
	if(a[x-1][y]!=a[x][y] && !b[x-1][y]) build(x-1,y,k);
	if(a[x][y+1]!=a[x][y] && !b[x][y+1]) build(x,y+1,k);
	if(a[x][y-1]!=a[x][y] && !b[x][y-1]) build(x,y-1,k);
}
int search(int x,int y)
{
	int ans=1;
	if(b[x+1][y]==b[x][y] && !c[x+1][y]) {c[x+1][y]=1; ans+=search(x+1,y);}
	if(b[x-1][y]==b[x][y] && !c[x-1][y]) {c[x-1][y]=1; ans+=search(x-1,y);}
	if(b[x][y+1]==b[x][y] && !c[x][y+1]) {c[x][y+1]=1; ans+=search(x,y+1);}
	if(b[x][y-1]==b[x][y] && !c[x][y-1]) {c[x][y-1]=1; ans+=search(x,y-1);}
	return ans;
}
int main()
{
	int x,y,k=1;
	string s;
	cin>>n>>m;
	memset(a,100,sizeof(a));
	for(int i=1;i<=n;i++)
	{
		cin>>s;
		for(int j=0;j<s.size();j++)
		    a[i][j+1]=s[j]-48;
	}//输入的时候是字符串,需要逐字处理 
	for(int i=1;i<=n;i++)
	    for(int j=1;j<=n;j++)
	        if(!b[i][j]){
	        	build(i,j,k);
	            k++;
			}//预处理 ,属于同一个大块的都有相同的K值 
	for(int k=1;k<=m;k++)
	{
		cin>>x>>y;
		int ans=0;
		memset(c,0,sizeof(c));
		c[x][y]=1;
		ans=search(x,y);//暴力搜索所属大块有几个点 
		cout<<ans<<endl;
	}
	return 0;
}

  

然后就想着改进:感觉每次都暴力数大块有几个点,假如几个点属于同一大块,不就重复数了吗,既然这样,再预处理一下,直接输出答案不就完美了(想到这,感觉这次肯定能AC了。。

(80分。。 这数据真的高级

#include <bits/stdc++.h>
using namespace std;
int a[1005][1005];
int b[1005][1005];
bool c[1005][1005];
int d[1005][1005];
int n,m;
void build(int x,int y,int k)
{
	if(x>n || x==0) return; if(y>n || y==0) return ;
	b[x][y]=k;
	if(a[x+1][y]!=a[x][y] && !b[x+1][y]) build(x+1,y,k);
	if(a[x-1][y]!=a[x][y] && !b[x-1][y]) build(x-1,y,k);
	if(a[x][y+1]!=a[x][y] && !b[x][y+1]) build(x,y+1,k);
	if(a[x][y-1]!=a[x][y] && !b[x][y-1]) build(x,y-1,k);
}
int search(int x,int y)
{
	int ans=1;
	if(b[x+1][y]==b[x][y] && !c[x+1][y]) {c[x+1][y]=1; ans+=search(x+1,y);}
	if(b[x-1][y]==b[x][y] && !c[x-1][y]) {c[x-1][y]=1; ans+=search(x-1,y);}
	if(b[x][y+1]==b[x][y] && !c[x][y+1]) {c[x][y+1]=1; ans+=search(x,y+1);}
	if(b[x][y-1]==b[x][y] && !c[x][y-1]) {c[x][y-1]=1; ans+=search(x,y-1);}
	return ans;
}
void build1(int x,int y,int k)//预处理,在d数组直接标出属于同一个大块的点的个数 
{
	if(x>n || x==0) return; if(y>n || y==0) return ;
	d[x][y]=k;
    if(b[x+1][y]==b[x][y] && !d[x+1][y]) {d[x+1][y]=k; build1(x+1,y,k);}
	if(b[x-1][y]==b[x][y] && !d[x-1][y]) {d[x-1][y]=k; build1(x-1,y,k);}
	if(b[x][y+1]==b[x][y] && !d[x][y+1]) {d[x][y+1]=k; build1(x,y+1,k);}
	if(b[x][y-1]==b[x][y] && !d[x][y-1]) {d[x][y-1]=k; build1(x,y-1,k);}
}
int main()
{
	int x,y,k=1;
	string s;
	cin>>n>>m;
	memset(a,100,sizeof(a));
	for(int i=1;i<=n;i++)
	{
		cin>>s;
		for(int j=0;j<s.size();j++)
		    a[i][j+1]=s[j]-48;
	}
	for(int i=1;i<=n;i++)
	    for(int j=1;j<=n;j++)
	        if(!b[i][j]){
	        	build(i,j,k);
	        	memset(c,0,sizeof(c));
	        	c[i][j]=1;
	        	int ans=search(i,j);//搜索出大块有几个点 
	        	build1(i,j,ans);//预处理 
	            k++;
			}
	for(int k=1;k<=m;k++)
	{
		cin>>x>>y;
		cout<<d[x][y]<<endl;//直接输出结果 
	}
	return 0;
}

  

然后实在撑不住,去看了题解。。

每次碰到没搜过的就进行一次搜索,碰到的就直接输出(用数组模拟队列来储存属于同一大块的点的坐标

#include <bits/stdc++.h>
using namespace std;
int a[1005][1005];
int c[1005][1005];
int d[1005][1005];
int xx[10000005],yy[1000005];
int n,m;
void search(int x,int y)
{
	int t=1,h=0,ans=0;
	while(h<t)//bfs的队列 
	{
	    h++;
	    x=xx[h]; y=yy[h];
		if(a[x+1][y]!=a[x][y] && !c[x+1][y] && x+1<=n) {t++; c[x+1][y]=1; xx[t]=x+1; yy[t]=y;}
        if(a[x-1][y]!=a[x][y] && !c[x-1][y] && x-1>0) {t++; c[x-1][y]=1; xx[t]=x-1; yy[t]=y;}
	    if(a[x][y+1]!=a[x][y] && !c[x][y+1] && y+1<=n) {t++; c[x][y+1]=1; xx[t]=x; yy[t]=y+1;}
	    if(a[x][y-1]!=a[x][y] && !c[x][y-1] && y-1>0) {t++; c[x][y-1]=1; xx[t]=x; yy[t]=y-1;}
	    
	}
	for(int i=1;i<=t;i++)
	    d[xx[i]][yy[i]]=t;//每个属于大块的点都标记上大块点的个数 
	return ;
}
int main()
{
	int x,y,k=1;
	string s;
	cin>>n>>m;
	memset(a,100,sizeof(a));
	for(int i=1;i<=n;i++)
	{
		cin>>s;
		for(int j=0;j<s.size();j++)
		    a[i][j+1]=s[j]-48;
	}
	for(int k=1;k<=m;k++)
	{
		cin>>x>>y;
		if(!d[x][y]) {c[x][y]=1; xx[1]=x; yy[1]=y; search(x,y);}//如果没搜过就搜 
		cout<<d[x][y]<<endl; 
	}
	return 0;
}

  

 

posted @ 2023-01-08 23:51  小霜降  阅读(13)  评论(0编辑  收藏  举报