NOIP 2011 Day1T3 Mayan游戏

     这道题耗了我整整一个下午,被读入坑了,然后还被各种坑,首先不知道为什么在栈中使用memcpy会崩掉,然后数组越界......

     这题就是一个搜索,考验代码能力和基本的模拟,一个非常有效的剪枝是我们对于向左移动,我们只搜左边没有方块的,因为如果它的左边有方块的话,它俩一定会在搜它左边的块的右边时交换过,剩下的就是模拟方块清除和方块下落的过程,对于方块清除操作,我们可以全部扫一遍,用一个标记数组,对于一个方块判断它上下,左右是否和它同色,如果同色就把它们都打上标签,最后一起处理,对于下落操作,我们可以从下到上扫,然后对于每一个格子看看它下面是不是空的,然后再进行处理。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int g[8][5],n,tot,ans1[10],ans2[10],ans3[10];
const int d[3]={0,-1,1};
bool vis[7][5];

void dfs(int a[7][5],int cur,int cnt) 
{
	if (cnt==0) 
	{
		if (cur==n)
		{
			for (int i=1;i<=cur;i++) printf("%d %d %d\n",ans1[i],ans2[i],ans3[i]);
			exit(0);
		}
		return;
	}
	if (cur==n) return;	
	int temp[7][5];
	for (int i=0;i<7;i++) 
		for (int j=0;j<5;j++) temp[i][j]=a[i][j];
	for (int j=0;j<5;j++) 
		for (int i=0;i<7;i++) 
		{
			if (a[i][j]==0)	continue;
			for (int k=2;k>=1;k--) 
			{
				if (j+d[k]<0||j+d[k]>4) continue;
				if (k==1&&a[i][j-1]) continue;
				swap(a[i][j],a[i][j+d[k]]);
				if (a[i][j]==0) 
				{
					int p=i-1;
					while (p>=0) 
						if (a[p][j+d[k]]==0) p--;else break;
					p++;
					swap(a[i][j+d[k]],a[p][j+d[k]]);
					for (int ii=1;ii<=6;ii++) 
					{
						if (a[ii][j]==0) continue;
						int p1=ii-1;
						while (p1>=0) 
							if (a[p1][j]==0) p1--;else break;
						p1++;
						swap(a[ii][j],a[p1][j]);	
					}
				}
				bool ok=1;
				int w=0;
				while (ok)
				{
					ok=0;
					memset(vis,0,sizeof vis);
					for (int ii=0;ii<7;ii++) 
						for (int jj=0;jj<5;jj++) 
						{
							if (ii-1>=0&&ii+1<=6) 
							{						
								if (a[ii][jj]&&a[ii-1][jj]==a[ii][jj]&&a[ii][jj]==a[ii+1][jj])
									vis[ii-1][jj]=vis[ii][jj]=vis[ii+1][jj]=1,ok=1;
							}
							if (jj-1>=0&&jj+1<=4) 
							{
								if (a[ii][jj]&&a[ii][jj-1]==a[ii][jj]&&a[ii][jj+1]==a[ii][jj]) 
									vis[ii][jj]=vis[ii][jj-1]=vis[ii][jj+1]=1,ok=1;
							}
						}
					if (ok==0) break;
					for (int ii=0;ii<7;ii++) 
						for (int jj=0;jj<5;jj++) 
						{
							if (a[ii][jj]==0) continue;
							if (vis[ii][jj]) 
							{
								w++;
								a[ii][jj]=0;
								continue;		
							}
							int p1=ii-1;
							while (p1>=0) 
							{
								if (a[p1][jj]==0) 
									p1--;
								else break;
							}
							p1++;
							swap(a[p1][jj],a[ii][jj]);
						}
				}
				ans1[cur+1]=j;ans2[cur+1]=i;
				if (k==2) ans3[cur+1]=1;else ans3[cur+1]=-1;
				dfs(a,cur+1,cnt-w);
				for (int ii=0;ii<7;ii++) 
					for (int jj=0;jj<5;jj++) a[ii][jj]=temp[ii][jj];
			}
		}
}

int main()
{
	scanf("%d",&n);
	for (int j=0;j<=4;j++) 
		for (int i=0;i<=7;i++) 
		{
			scanf("%d",&g[i][j]);
			if (g[i][j]==0) break;	
			tot++;
		}
	dfs(g,0,tot);
	printf("-1\n");
	return 0;
}	


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值