mayan游戏


题解:

非常暴力的一道题
因为地图比较小,枚举35块所有向左拉或者向右拉总共70种情况
输出一个字典序最小的一个答案,事实上是降低了深搜难度
按从小到大依次搜索x和y,先向右拉,再向左拉,对于每一次拉动
先交换两个方块,然后将这两列的方块全部落下,这就需要我们写一个“掉落”函数
掉落完成后,进行“清除”操作,规则跟一般的三消游戏差不多
清除操作必须将当前能消除的全部消除,另外消除完后还要将悬空的方块落下
注意落下之后还有可能继续消除,因此要用递归或者while循环直到完全不能再清除 
深搜完成后,还原现场显得与平常的深搜不同,我们需要在每一层中都定义一个临时的
数组来保存原地图,然后用memcpy还原现场


掉落函数
定义一个浮标,当前行有数字时移动浮标,为0时不移动
这就可以将悬空的方块移下来了


清除函数
找所有35个方块,若左右两边或者上下的颜色相同,则将它们赋为0
然后执行掉落函数,继续消除 


因为此题给了步数,边界就很好判定了,当达到规定步数并且所有方块都为0

则到达边界,并且能保证字典序最小

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
#include<climits>
#define MAXA 10
using namespace std;
int mayan[MAXA][MAXA],n,Ans[MAXA][MAXA];
void Fall_Down(int lie) {
	int cnt = -1;
	for(int i=0;i<7;i++)
	    if(mayan[lie][i])
	       mayan[lie][++cnt] = mayan[lie][i];
	for(int i=cnt+1;i<7;i++)
	    mayan[lie][i] = 0;
	return;
}
void Clear() {
	bool flag = true;
	while(flag) {
		flag = false;
		int temp[10][10];
		memcpy(temp,mayan,sizeof(temp));
		for(int i=0;i<5;i++)
		    for(int j=0;j<7;j++) {
		    	if(i >= 1 && i <= 3 && temp[i][j] && temp[i][j] == temp[i-1][j] && temp[i][j] == temp[i+1][j]) {
		        	mayan[i][j] = 0;
					mayan[i-1][j] = 0;
		        	mayan[i+1][j] = 0;
		        	flag = true;
				}
				if(j >= 1 && j <= 5 && temp[i][j] && temp[i][j] == temp[i][j-1] && temp[i][j] == temp[i][j+1]) {
					mayan[i][j] = 0;
					mayan[i][j-1] = 0;
					mayan[i][j+1] = 0;
					flag = true;
				}
			}
		        
		if(!flag)
		   return;
		for(int i=0;i<5;i++)
		    Fall_Down(i);
	}
}
void PushAns(int i,int x,int y,int type) { //更新答案 
	Ans[i][1] = x;
	Ans[i][2] = y;
	Ans[i][3] = type;
}
bool isComplete() { //判断是否全部消完 
	for(int i=0;i<5;i++)
	    for(int j=0;j<7;j++)
	        if(mayan[i][j])
	           return 0;
	return 1;
}
void DFS(int step) {
	if(isComplete() && step == n) {
		for(int i=1;i<=step;i++)
		    printf("%d %d %d\n",Ans[i][1],Ans[i][2],Ans[i][3]);
		exit(0);
	}
	if(step >= n)
	   return;
	int temp[10][10];
	memcpy(temp,mayan,sizeof(temp));
	for(int i=0;i<5;i++)
	    for(int j=0;j<7;j++) {
	    	if(!mayan[i][j])
	    	   continue;
	    	if(i != 4) {
	    	   swap(mayan[i][j],mayan[i+1][j]);
	    	   Fall_Down(i);
	    	   Fall_Down(i + 1);
	    	   Clear();
	    	   PushAns(step+1,i,j,1);
	    	   DFS(step + 1);
	    	   PushAns(step+1,0,0,0);
	    	   memcpy(mayan,temp,sizeof(mayan));
			}
			if(i && !mayan[i-1][j]) {
				swap(mayan[i][j],mayan[i-1][j]);
				Fall_Down(i);
				Fall_Down(i - 1);
				Clear();
				PushAns(step+1,i,j,-1);
				DFS(step + 1);
				PushAns(step+1,0,0,0);
				memcpy(mayan,temp,sizeof(mayan));
			}
		}
}
int main() {

	scanf("%d",&n);
	for(int i=0;i<5;i++) {
		int p = 0;
		do {
			cin >> mayan[i][p];
			p++;
		}while(mayan[i][p-1] != 0);
	}
	DFS(0);
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值