版权声明:本文为博主原创作品, 转载请注明出处! 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;
}