搜索_DFS_CH2903_Mayan游戏

版权声明:本文为博主原创作品, 转载请注明出处! https://blog.csdn.net/solider98/article/details/84191128

点此打开题目页面

思力分析:

    使用DFS, 考虑如下剪枝策略

    (1)如果交换的两个数相同, 可剪枝

    (2)如果两个数均对应颜色(非空格), 那么只需执行左侧数的交换, 对右侧数可直接剪枝(如下代码中第88行所示)

    根据上述剪枝策略, 给出如下AC代码:

//CH2903_Mayan游戏
#include <iostream>
#include <cstring>
#include <vector>
#define fi first
#define se second
#define mp make_pair
using namespace std;
const int NIL = 0x3f3f3f3f;
char G[8][6], L[6]; int n;//L[i]: 第i列中有效元素个数 
int ok; vector<pair<pair<int, int>, int> > path;
//如果当前G中所有元素均为0则返回true, 否则返回false 
bool check(){
	for(int i = 1; i <= 5; ++i) if(L[i]) return false;
	return true;
}
//处理第c列的掉落
void drop(int c){
	int k = 0; 
	for(int i = 1, t; i <= 7; ++i) if(G[i][c]) t = G[i][c], G[i][c] = 0, G[++k][c] = t;
	L[c] = k;
} 
//处理消除
void remove(){
	bool finsh = false;//为false表示不可以继续消除 
	while(!finsh){
		finsh = true;
		char tg[8][6]; memcpy(tg, G, sizeof(G));
		int maxL = -NIL; for(int i = 1; i <= 5; ++i) maxL = max(maxL, (int)L[i]);
		//处理同一行中的消除
		for(int i = 1; i <= maxL; ++i){
			int l = 1, r = 1;
			for(int j = 2; j <= 5; ++j)
				if(tg[i][j] == tg[i][j - 1]) ++r;
				else{
					if(tg[i][r] && r - l >= 2) 
						for(int k = l; k <= r; ++k) G[i][k] = 0, finsh = false;
					l = r = j;
				}
			if(tg[i][r] && r == 5 && r - l >= 2) 
				for(int k = l; k <= r; ++k) G[i][k] = 0, finsh = false;		

		}			
		//处理同一列中的消除
		for(int i = 1; i <= 5; ++i){
			if(L[i] <= 2) continue;
			int l = 1, r = 1;
			for(int j = 2; j <= L[i]; ++j)
				if(tg[j][i] == tg[j - 1][i]) ++r;
				else{
					if(tg[r][i] && r - l >= 2) 
						for(int k = l; k <= r; ++k) G[k][i] = 0, finsh = false;
					l = r = j;
				}
			if(tg[r][i] && r == L[i] && r - l >= 2) 
				for(int k = l; k <= r; ++k) G[k][i] = 0, finsh = false;
		} 
		//处理掉落
		for(int i = 1; i <= 5; ++i) drop(i);
	}
} 
//交换G[x][a]和G[x][b]并处理掉落和消除
void gSwap(int a, int b, int x){
	swap(G[x][a], G[x][b]), drop(a), drop(b);
	remove();
}  
void dfs(){
	if(check()){
		if(path.size() == n){
			ok = 1; return;
		}
		return;
	}	
	if(path.size() == n) return;
	char tG[8][6], tL[6]; memcpy(tG, G, sizeof(G)), memcpy(tL, L, sizeof(L));
	vector<pair<pair<int, int>, int> > tpath = path;
	int maxL = -NIL; for(int i = 1; i <= 5; ++i) maxL = max(maxL, (int)L[i]);	
	for(int j = 1; j <= 5; ++j){
		if(!L[j]) continue;
		for(int i = 1; i <= L[j]; ++i)
			if(G[i][j]){
				if(j <= 4 && G[i][j] != G[i][j + 1]){					
					gSwap(j, j + 1, i), path.push_back(mp(mp(j, i), 1)), dfs(); 
					if(ok) return;
					memcpy(G, tG, sizeof(G)), memcpy(L, tL, sizeof(L)), path = tpath;
				}
				if(j >= 2 && G[i][j] != G[i][j - 1]){
					if(L[j] >= i && L[j - 1] >= i) continue;
					gSwap(j, j - 1, i), path.push_back(mp(mp(j, i), -1)), dfs();
					if(ok) return;
					memcpy(G, tG, sizeof(G)), memcpy(L, tL, sizeof(L)), path = tpath;
				}
			}
	}
}
int main(){
	cin >> n;
	for(int i = 1; i <= 5; ++i)
		for(int j = 1; j <= 8; ++j){
			int t; cin >> t; 
			if(!t) break; else G[j][i] = t, ++L[i];
		}
	dfs(); 
	if(!ok) cout << "-1" << endl;
	else 
		for(int i = 0; i < path.size(); ++i) 
			cout << path[i].fi.fi - 1 << " " << path[i].fi.se - 1 << " " << path[i].se << endl;	

	return 0;
}

    

猜你喜欢

转载自blog.csdn.net/solider98/article/details/84191128