NOIP2011 Mayan游戏 搜索

版权声明:本文为DyingShu原创文章,转载请注明出处哦。 https://blog.csdn.net/DyingShu/article/details/82054079

传送门

题解:爆搜+剪枝
要注意以下几点:

  • 向右搜时,若颜色一样则不搜
  • 向左搜时,若不是空格,则不搜(因为此时它左边的方块已经向右搜索过了)
  • 可以把搜索过程想象成一颗搜索树,这样只用开与这棵树的深度成正比的状态数组
  • DFS时先考虑右移,因为右移优先度比左移高

具体见代码吧~

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int MAXN = 11;

int n, Total;
int Now_Plate[MAXN][MAXN][MAXN]; //第i层 第i列 高度为j 
bool tag[MAXN][MAXN];
int Ans[MAXN][3];

inline int read(){
	int k = 0, f = 1; char ch = getchar();
	while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}
	while(ch >= '0' && ch <= '9'){k = k*10 + ch - '0'; ch = getchar();}
	return k * f;
}

void Fall_Down(int u){ //处理Now_Plate的掉落
	for(int i = 1; i <= 5; i++){
		int temp = 0;
		for(int j = 1; j <= 7; j++){
			if(Now_Plate[u][i][j]){
				Now_Plate[u][i][++temp] = Now_Plate[u][i][j];
			}
		}
		for(int j = temp + 1; j <= 7; j++){
			Now_Plate[u][i][j] = 0;
		}
	}
}

void Clear(int u){ //对Now_Plate进行消除
	for(bool flag = true; flag;){
		flag = false; Fall_Down(u); //记录消除
		for(int i = 1; i <= 5; i++){
			for(int j = 1; j <= 7; j++){
				if(!Now_Plate[u][i][j]) continue;
				//处理横着的
				if(i <= 3){
					if(Now_Plate[u][i][j] == Now_Plate[u][i + 1][j] && Now_Plate[u][i][j] == Now_Plate[u][i + 2][j]){
						flag = tag[i][j] = tag[i + 1][j] = tag[i + 2][j] = true;
					}
				}
				//处理竖着的
				if(j <= 5){
					if(Now_Plate[u][i][j] == Now_Plate[u][i][j + 1] && Now_Plate[u][i][j] == Now_Plate[u][i][j + 2]){
						flag = tag[i][j] = tag[i][j + 1] = tag[i][j + 2] = true;
					}
				}
			}
		}
		for(int i = 1; i <= 5; i++){
			for(int j = 1; j <= 7; j++){
				if(tag[i][j]){
					Now_Plate[u][i][j] = tag[i][j] = 0;
				}
			}
		}
	}
}

bool dfs(int u){ //第几步
//	Total++;
	for(int i = 1; i <= 5; i++){
		for(int j = 1; j <= 7; j++){
			Now_Plate[u][i][j] = Now_Plate[u - 1][i][j];
		}
	}
	Clear(u);
	if(u > n){
		for(int i = 1; i <= 5; i++){
			if(Now_Plate[u][i][1]) return false;
		}
		return true;
	}
	
	for(int i = 1; i <= 5; i++){
		for(int j = 1; j <= 7; j++){
			if(!Now_Plate[u][i][j]) continue;
			//试图向右
			if(i < 5 && Now_Plate[u][i][j] != Now_Plate[u][i + 1][j]){//不一样才有意义
				Ans[u][0] = i - 1, Ans[u][1] = j - 1, Ans[u][2] = 1;
				swap(Now_Plate[u][i][j], Now_Plate[u][i + 1][j]);
				if(dfs(u + 1)) return true;
				swap(Now_Plate[u][i][j], Now_Plate[u][i + 1][j]);
			}
			//试图向左
			if(i > 1 && !Now_Plate[u][i - 1][j]){
				Ans[u][0] = i - 1, Ans[u][1] = j - 1, Ans[u][2] = -1;
				swap(Now_Plate[u][i][j], Now_Plate[u][i - 1][j]);
				if(dfs(u + 1)) return true;
				swap(Now_Plate[u][i][j], Now_Plate[u][i - 1][j]);
			}
		}
	}
	return false;
}

int main(){
	freopen("in.txt", "r", stdin);
	n = read();
	for(int i = 1; i <= 5; i++){
		for(int j = 1; j <= 8; j++){
			int x = read();
			if(!x) break;
			Now_Plate[0][i][j] = x;
		}
	}
	if(dfs(1)){
		for(int i = 1; i <= n; i++){
			for(int j = 0; j < 3; j++){
				printf("%d ", Ans[i][j]);
			}
			printf("\n");
		}
	}
	else printf("-1");
//	printf("\n");
//	printf("Total = %d", Total);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/DyingShu/article/details/82054079