NOIP2011 Mayan遊戲 搜索

傳送門

題解:爆搜+剪枝
要注意以下幾點:

  • 向右搜時,若顏色一樣則不搜
  • 向左搜時,若不是空格,則不搜(因爲此時它左邊的方塊已經向右搜索過了)
  • 可以把搜索過程想象成一顆搜索樹,這樣只用開與這棵樹的深度成正比的狀態數組
  • 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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章