2026暑假 [连块消除] 题解
这道题和上一道题一样,也是模拟,循环操作直到删不了了为止。
每次操作可以拆分成多个步骤,首先,对于每一个方块,找它的连通块,统计这个连通块的方块个数。
然后,去判断这个连通块大小是否大于 \(K\),如果它确实满足要求,就去把这个连通块都变成 \(0\)。
但是它还有个重力要求,所以我们在遇到一个 \(0\) 时就将一个标记 \(kkk\) 增加,遇到一个不是 \(0\) 的就让他下移 \(kkk\) 个。
最后愉快输出整个矩阵就行了。
代码 $\downarrow$
#include<bits/stdc++.h>
using namespace std;
int n,k,a[102][12];
int hx[4]={0,1,0,-1};
int hy[4]={1,0,-1,0};
bool f[102][12];
int dfs(int x,int y,int z)
{
int sum=1;
f[x][y]=1;
for(int i=0;i<4;i++)
{
int dx=x+hx[i];
int dy=y+hy[i];
if(dx>=1&&dx<=n&&dy>=1&&dy<=10&&!f[dx][dy]&&a[dx][dy]==z)
{
sum+=dfs(dx,dy,z);
}
}
return sum;
}
void dfs2(int x,int y,int z)
{
a[x][y]=0;
for(int i=0;i<4;i++)
{
int dx=x+hx[i];
int dy=y+hy[i];
if(dx>=1&&dx<=n&&dy>=1&&dy<=10&&a[dx][dy]==z)
{
dfs2(dx,dy,z);
}
}
return;
}
bool f1()
{
memset(f,0,sizeof(f));
bool g=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=10;j++)
{
if(!f[i][j]&&a[i][j]!=0)
{
if(dfs(i,j,a[i][j])>=k)
{
g=1;
dfs2(i,j,a[i][j]);
}
}
}
}
return g;
}
void f2()
{
for(int j=1;j<=10;j++)
{
int kkk=0;
for(int i=n;i>=1;i--)
{
if(a[i][j]==0)
{
kkk++;
}
else
{
swap(a[i][j],a[i+kkk][j]);
}
}
}
return;
}
int main()
{
freopen("mooyo.in","r",stdin);
freopen("mooyo.out","w",stdout);
cin>>n>>k;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=10;j++)
{
char c;
cin>>c;
a[i][j]=c-'0';
}
}
while(f1())f2();
for(int i=1;i<=n;i++)
{
for(int j=1;j<=10;j++)
{
cout<<a[i][j];
}
cout<<"\n";
}
return 0;
}
( ^_^ )
浙公网安备 33010602011771号