【usaco2018dec_silver_T3】mooyo (dfs- flood-fill)

来源:JZOJ

题目描述

由于手上(更确实的,蹄子上)有大把的空余时间, F a r m e r J o h n Farmer John 的农场里的奶牛经常玩电子游戏消磨时光。她们最爱的游戏之一是基于一款流行的电子游戏 P u y o P u y o Puyo Puyo 的奶牛版;名称当然叫做 M o o y o Mooyo

M o o y o Mooyo 是在一块又高又窄的棋盘上进行的游戏,高 N 1 N 1001 N 100 N (1≤N≤100 1≤N≤100) 格,宽 10 10 格。 这是一个 N = 6 N=6 的棋盘的例子:

0000000000
0000000300
0054000300
1054502230
2211122220
1111111223

每个格子或者是空的(用 0 0 表示),或者是九种颜色之一的干草捆(用字符 1 9 1…9 表示)。重力会使得干草捆下落,所以没有干草捆的下方是 0 0

如果两个格子水平或垂直方向直接相邻,并且为同一种非 0 0 颜色,那么这两个格子就属于同一个连通区域。任意时刻出现至少 K K 个格子构成的连通区域,其中的干草捆就会全部消失,变为 0 0 。如果同时出现多个这样的连通区域,它们同时消失。随后,重力可能会导致干草捆向下落入某个变为 0 0 的格子。由此形成的新的布局中,又可能出现至少 K K 个格子构成的连通区域。若如此,它们同样也会消失(如果又有多个这样的区域,则同时消失),然后重力又会使得剩下的方块下落,这一过程持续进行,直到不存在大小至少为K的连通区域为止。

给定一块 M o o y o Mooyo 棋盘的状态,输出这些过程发生之后最终的棋盘的图案。

解题思路

  • 这道题分为几个步骤来做
  • 先求连通块,如果有 > = k >=k 的,那么就清 0 0 ,然后下落;
  • 思路很简单,但是代码调试还是有一点难度的(千万不要手贱 Q A Q \large{QAQ}

美妙的 C o d e Code 时间、

#include <bits/stdc++.h>
using namespace std;
int fx[4]={0,0,1,-1};
int fy[4]={1,-1,0,0};
int n,k,sum=0;
int f[105][105],a[105][105];
void dfs(int x,int y,int s)  //统计连通块
{
	f[x][y]=1;
	for (int i=0;i<4;i++)
	{
		int xx=x+fx[i],yy=y+fy[i];
		if (xx<1 || xx>n || yy<1 || yy>10) continue;
		if (a[xx][yy]!=s || f[xx][yy]) continue;
		sum++;
		dfs(xx,yy,s);
	}
}
void remove(int x,int y,int s)  //清0
{
	f[x][y]=1;
	for (int i=0;i<4;i++)
	{
		int xx=x+fx[i],yy=y+fy[i];
		if (xx<1 || xx>n || yy<1 || yy>10) continue;
		if (a[xx][yy]!=s || f[xx][yy]) continue;
		remove(xx,yy,s);
	}
	a[x][y]=0;
}
void drop()  //处理下落
{
	for (int i=n;i>=1;i--)
	 for (int j=1;j<=10;j++)
	 {
	 	if (a[i][j]!=0)
	  	{
	  		int k=i;
	  		while (k<n && !a[k+1][j]) k++;
	  		if (k!=i)
	  		{
	  			a[k][j]=a[i][j];
	  			a[i][j]=0;
			}
	  	}
	 }
}
void work()
{
	bool flag=1;
	while (flag)  //如果没有到最终状态
	{
		flag=0;
		for (int i=1;i<=n;i++)
		 for (int j=1;j<=10;j++)
		 {
		 	if (!a[i][j]) continue;
		 	memset(f,0,sizeof(f));
		 	sum=1;
		 	dfs(i,j,a[i][j]);
		 	if (sum>=k)  //找到大于等于k的连通块
		 	{
		 		flag=1;
		 		memset(f,0,sizeof(f));
		 		remove(i,j,a[i][j]);  //清0
			}
		 }
		if (flag)
		{
			drop();  //如果有清0的情况就执行下落
		}
	}
}
int main()
{
	freopen("mooyo.in","r",stdin);
	freopen("mooyo.out","w",stdout);
	scanf("%d %d",&n,&k);
	for (int i=1;i<=n;i++)
	 for (int j=1;j<=10;j++)
	 {
	 	scanf("%1d",&a[i][j]);
	 }
	work();
	for (int i=1;i<=n;i++)
	{
		for (int j=1;j<=10;j++) printf("%d",a[i][j]);
		printf("\n");
	}
	return 0;
}
发布了34 篇原创文章 · 获赞 39 · 访问量 3826

猜你喜欢

转载自blog.csdn.net/qq_43081996/article/details/104332603
今日推荐