Mayan游戏[NOIP2011]

版权声明:作为一个蒟蒻,转载时请通知我这个蒟蒻 https://blog.csdn.net/zyszlb2003/article/details/89450733

欢迎大家访问我的老师的OJ———caioj.cn

题面描述

传送门

思路

由于输入 bt \large \operatorname{bt} ,我们把行和列调换一下。
这道题真的好考耐心啊。
首先,我们先把判断正确性的函数给弄出来。

bool pd()
{
	for(int i=0;i<5;i++)
		for(int j=0;j<7;j++)
			if(a[i][j])return 0;
	return 1;
}

再把消除方块的函数给写出来。
说明:由于我们只要满足竖着或横着的三个或以上的相同颜色就能达到条件消除。
所以我们需要横着枚举一遍,竖着再枚举一遍。
由于我们横着拓展时,可能会出现竖着的满足条件,所以在这里也要加以判断。
竖着的同理。

bool work()
{
	bool flag=0;
	for(int i=0;i<3;i++)
		for(int j=0;j<7;j++)
		{
			if(a[i][j])
			{
				int t=i;
				while(t<4&&a[t+1][j]==a[i][j])t++;
				if(t-i>=2)
				{
					int x=i;
					while(x<=t)
					{
						int p,q;p=q=j;
						while(p<6&&a[x][p+1]==a[i][j])p++;
						while(q>0&&a[x][q-1]==a[i][j])q--;
						if(p-q>=2)
							for(int y=q;y<=p;y++)a[x][y]=0;
						++x;
					}
					for(int z=i;z<=t;z++)a[z][j]=0;
					flag=1;
				}
			}
		}
	for(int i=0;i<5;i++)
		for(int j=0;j<5;j++)
		{
			if(a[i][j])
			{
				int t=j;
				while(t<6&&a[i][t+1]==a[i][t])t++;
				if(t-j>=2)
				{
					int y=j;
					while(y<=t)
					{
						int p,q;p=q=i;
						while(p<4&&a[p+1][y]==a[i][j])p++;
						while(q>0&&a[q-1][y]==a[i][j])q--;
						if(p-q>=2)
							for(int x=q;x<=p;x++)a[x][y]=0;
						++y;
					}
					for(int z=j;z<=t;z++)a[i][z]=0;
					flag=1;
				}
			}
		}
	return flag;
}

每一次消除方块的时候,我们有可能会发现,会有一些方块悬浮在空中,所以我们需要一个 down \operatorname{down} 函数。

void down()
{
	int num[N][N];memset(num,-1,sizeof(num));
	for(int i=0;i<5;i++)
	{
		int k=0;
		for(int j=0;j<7;j++)
			if(a[i][j])num[i][k++]=j;
	}
	for(int i=0;i<5;i++)
		for(int j=0;j<7;j++)
			a[i][j]=(num[i][j]==-1)?0:a[i][num[i][j]];
}

一个好的 down \operatorname{down} 函数可以快很多。
接下来就没什么好讲的了。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
using namespace std;
const int N=10;
struct node
{
	int x,y;bool z;
}ans[N];
int a[N][N],n;
bool pd()
{
	for(int i=0;i<5;i++)
		for(int j=0;j<7;j++)
			if(a[i][j])return 0;
	return 1;
}
void down()
{
	int num[N][N];memset(num,-1,sizeof(num));
	for(int i=0;i<5;i++)
	{
		int k=0;
		for(int j=0;j<7;j++)
			if(a[i][j])num[i][k++]=j;
	}
	for(int i=0;i<5;i++)
		for(int j=0;j<7;j++)
			a[i][j]=(num[i][j]==-1)?0:a[i][num[i][j]];
}
bool work()
{
	bool flag=0;
	for(int i=0;i<3;i++)
		for(int j=0;j<7;j++)
		{
			if(a[i][j])
			{
				int t=i;
				while(t<4&&a[t+1][j]==a[i][j])t++;
				if(t-i>=2)
				{
					int x=i;
					while(x<=t)
					{
						int p,q;p=q=j;
						while(p<6&&a[x][p+1]==a[i][j])p++;
						while(q>0&&a[x][q-1]==a[i][j])q--;
						if(p-q>=2)
							for(int y=q;y<=p;y++)a[x][y]=0;
						++x;
					}
					for(int z=i;z<=t;z++)a[z][j]=0;
					flag=1;
				}
			}
		}
	for(int i=0;i<5;i++)
		for(int j=0;j<5;j++)
		{
			if(a[i][j])
			{
				int t=j;
				while(t<6&&a[i][t+1]==a[i][t])t++;
				if(t-j>=2)
				{
					int y=j;
					while(y<=t)
					{
						int p,q;p=q=i;
						while(p<4&&a[p+1][y]==a[i][j])p++;
						while(q>0&&a[q-1][y]==a[i][j])q--;
						if(p-q>=2)
							for(int x=q;x<=p;x++)a[x][y]=0;
						++y;
					}
					for(int z=j;z<=t;z++)a[i][z]=0;
					flag=1;
				}
			}
		}
	return flag;
}
void dfs(int now)
{
	if(now>n)
	{
		if(pd())
		{
			for(int i=1;i<=n;i++)
				if(ans[i].z)printf("%d %d -1\n",ans[i].x+1,ans[i].y);
				else printf("%d %d 1\n",ans[i].x,ans[i].y);
			exit(0);
		}
		return ;
	}
	int num[11];memset(num,0,sizeof(num));
	for(int i=0;i<5;i++)
		for(int j=0;j<7;j++)
			++num[a[i][j]];
	for(int i=1;i<=10;i++)if(num[i]==1||num[i]==2)return ;
	int c[N][N];memcpy(c,a,sizeof(a));
	for(int i=0;i<4;i++)
	{
		for(int j=0;j<7;j++)
		{
			if(a[i][j]!=a[i+1][j])
			{
				ans[now].x=i;
				ans[now].y=j;
				ans[now].z=(!a[i][j]);
				//如果!a[i][j]==true,说明a[i][j]为空,所以我们要将
				//a[i+1][j]往左移,交换位置。
				swap(a[i+1][j],a[i][j]);
				down();
				while(work())down();
				dfs(now+1);
				memcpy(a,c,sizeof(c));
			}
		}
	}
}
int main()
{
	scanf("%d",&n);memset(a,0,sizeof(a));
	for(int i=0;i<5;i++)
		for(int j=0;;j++)
		{
			scanf("%d",&a[i][j]);
			if(!a[i][j])break;
		}
	dfs(1);
	puts("-1");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/zyszlb2003/article/details/89450733