版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Fantasy_World/article/details/81876425
一个有效的剪枝是排除等效冗沉,当两种操作形成等效效果时不重复搜索
若有两个块,那么左边的右移和右边的左移是等效的,由于题意认为右移优先于左移,所以这种情况只取右移,而一个块左边是空的时候则要尝试左移
在回溯法“还原”的时候,可以先复制出来局面,在函数里开数组(别用全局的,要保存多个局面),然后复制回去
但仔细想想不需要再复制回去了,大不了每次都开个数组,直接当dfs的参数传下去,然后每次dfs用参数表里的数组就是了
因为一开始我没想到那个“左右移等效”,为了不让一个块来回左右走许多次,我记了个lasti 表示上一次移动的块的坐标,但是lasti初始值应为-1 因为 0,0 也是合法的坐标,并且lasti应该在参数表里而不是全局定义
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
#define debug(x) cerr << #x << "=" << x << endl;
const int MAXN = 100;
int g[MAXN][MAXN], n, h[MAXN], cg[10][10], fg[10][10],ans[10][10],sum[10];
bool flg = false, now_flg;
void copy(int a[5][7]) {
for(int i=0; i<5; i++)
for(int j=0; j<7; j++)
a[i][j] = g[i][j];
}
void reco(int a[5][7]) {
for(int i=0; i<5; i++)
for(int j=0; j<7; j++)
g[i][j] = a[i][j];
}
void tran() {
for(int i=0; i<7; i++)
for(int j=0; j<=2; j++)
if(g[j][i] == g[j+1][i] && g[j][i] == g[j+2][i] && g[j+1][i] == g[j+2][i] && g[j][i]) {
now_flg = true;
for(int k=0; k<=2; k++)
fg[j+k][i] = 1;
}
}
void vert() {
for(int i=0; i<5; i++)
for(int j=0; j<=4; j++)
if(g[i][j] == g[i][j+1] && g[i][j] == g[i][j+2] && g[i][j+1] == g[i][j+2] && g[i][j]) {
now_flg = true;
for(int k=0; k<=2; k++)
fg[i][j+k] = 1;
}
}
void corr() {
for(int i=0; i<5; i++)
for(int j=0; j<7; j++)
if(fg[i][j])
g[i][j] = 0;
for(int i=0; i<5; i++) {
for(int j=0; j<7; j++)
if(!g[i][j])
sum[j] = sum[j-1] + 1;
else sum[j] = sum[j-1];
for(int j=0; j<7; j++)
if(g[i][j]) {
g[i][j-sum[j]] = g[i][j];
if(sum[j]) g[i][j] = 0;
}
}
memset(fg, 0, sizeof(fg));
}
void modify(int x, int y, int mx) {
corr();
do {
now_flg = false;
tran();
vert();
corr();
} while(now_flg);
}
bool check() {
int total = 0;
for(int i=0; i<7; i++)
for(int j=0; j<5; j++)
total += g[i][j];
if(!total)
return true;
else return false;
}
void dfs(int x, int lasti, int lastj) {
if(x == n + 1) {
if(check()) {
flg = true;
return;
}
return;
}
for(int i=0; i<5; i++)
for(int j=0; j<7; j++) {
if(!g[i][j] || (i == lasti && j == lastj))
continue;
if(flg) return;
int tem[5][7];
if(i != 4) {
copy(tem);
swap(g[i][j], g[i+1][j]);
modify(i, j, i+1);
ans[x][0] = i, ans[x][1] = j, ans[x][2] = 1;
dfs(x+1, i, j);
if(flg) return;
reco(tem);
}
if(i != 0 && g[i-1][j] == 0) {
copy(tem);
swap(g[i][j], g[i-1][j]);
modify(i, j, i-1);
ans[x][0] = i, ans[x][1] = j, ans[x][2] = -1;
dfs(x+1, i, j);
if(flg) return;
reco(tem);
}
}
}
int main() {
cin >> n;
for(int i=0; i<5; i++) {
int noww = 0;
int x;
do{
scanf("%d", &x);
g[i][noww++] = x;
}while(x != 0);
}
dfs(1, -1, -1);
if(flg)
for(int i=1; i<=n; i++)
printf("%d %d %d\n", ans[i][0], ans[i][1], ans[i][2]);
else printf("-1");
return 0;
}