题解: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号