题解:P10379 [GESP202403 七级] 俄罗斯方块
题目通道
使用洪水填充法从每个未扫描过的点开始填充,得到一个数字相同的图形。判断此图形是否有相同图形。求出不同图形的个数。
思路:
- 
如何填充。和 DFS 差不多。建立两个方向数组 \(dx\) 和 \(dy\)。一个二维数组 \(v\) 用于标记是否填充过。如果下一个填充点未出界未访问过并与此填充的数字相同,就填充。
 - 
如何判断填充完的图形是否有相同图形。首先可以想到用 map 最快最方便。然后考虑用 string 来储存填充的每个数字,记住拐角时一定要在字符串里加个空格,方便区分。每次使用完后记得初始化。不要回溯。
 
代码:
#include<bits/stdc++.h>
using namespace std;
int n,m,s[505][505],v[505][505],ans;
map<string ,int> MP;
string as;
int dx[]={1,0,-1,0};
int dy[]={0,1,0,-1};  //方向数组
void dfs(int x,int y){
	for(int i=0;i<4;i++){
		int tx=x+dx[i],ty=y+dy[i];
		if(tx>=1&&tx<=n&&ty>=1&&ty<=m&&v[tx][ty]==0&&s[tx][ty]==s[x][y]){//判断合法
			as+=(i+'0');
			v[tx][ty]=1;//标记
			dfs(tx,ty);
		}
	}
	as+=' ';
}
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++) cin>>s[i][j];
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(v[i][j]==0){//没填充过就填充
				v[i][j]=1;
				as="";
				dfs(i,j);
				if(MP[as]==0) ans++;
				MP[as]=1;//标记
			}
		}
	}
	cout<<ans;
	return 0;
}

                
            
浙公网安备 33010602011771号