2026暑假 [连块消除] 题解

题目传送门1:
题目传送门2:

这道题和上一道题一样,也是模拟,循环操作直到删不了了为止。
每次操作可以拆分成多个步骤,首先,对于每一个方块,找它的连通块,统计这个连通块的方块个数。
然后,去判断这个连通块大小是否大于 \(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;
}

( ^_^ )

posted on 2026-07-18 10:19  hyh0926  阅读(8)  评论(0)    收藏  举报