DFS的剪枝:
1.相同颜色的方块可以跳过(显而易见);
2.还有一个比较难想的剪枝:
结论:只有右边有方块才move,左边没有方块才move;
证明(自己瞎写的):
(你正在搜i列)若左面有方块,那么你会在搜i-1列时将其右移,和你在i列时左移是等效的,所以可以减掉;
//My AC Code:
#include <cstdio>
#include<cstdlib>
using namespace std;
int map[6][9],cf[6][6][8];
int xd[6][8];
int ans[6][5];
int n,js;
void cp(int x){
for(int i=1;i<=5;i++)
for(int j=1;j<=7;j++)
cf[x][i][j]=map[i][j];
}
void update(){//检查 是否有消除,然后 让方块下落
for(int i=1;i<=5;i++){
int xa=0;
for(int j=1;j<=7;j++){
if(!map[i][j])xa++;
else {
if(!xa)continue;//因为如果空白为0 则表示当前方块下面没有被消除掉的方块
map[i][j-xa]=map[i][j];
map[i][j]=0;
}
}
}
}
bool remv(){
bool flag=false;
for(int i=1;i<=5;i++){
for(int j=1;j<=7;j++){
if(i-1>=1&&i+1<=5&&map[i][j]&&map[i-1][j]==map[i][j]&&map[i][j]==map[i+1][j]){
xd[i-1][j]=1;xd[i][j]=1;xd[i+1][j]=1;flag=true;
}
if(j-1>=1&&j+1<=7&&map[i][j]&&map[i][j-1]==map[i][j]&&map[i][j]==map[i][j+1]){
xd[i][j-1]=1;xd[i][j+1]=1;xd[i][j]=1;flag=true;
}
}
}
if(!flag)return 0;
for(int i=1;i<=5;i++)
for(int j=1;j<=7;j++)
if(xd[i][j]){
map[i][j]=0;
xd[i][j]=0;
}
return 1;
}
void move(int a,int b,int c){
int tp=map[a][b];
map[a][b]=map[a+c][b];
map[a+c][b]=tp;
update();
while(remv())update();
/*
移动后更新方块位置,有可能更新完之后 有方块可以消除,然后继续消除,知道 没有方块可以消除为止
*/
}
bool check(){
for(int i=1;i<=5;i++)
if(map[i][1])return 0;
return 1;
}
void dfs(int x){
if(check()){
for(int i=1;i<=n;i++){
for(int j=1;j<=3;j++){
printf("%d ",ans[i][j]);
}
printf("\n");
}
exit(0);
}
if(x==n+1)return;//要搜索到n 也就是第n步,因为前面有判断有没有全部消除
cp(x);
for(int i=1;i<=5;i++){
for(int j=1;j<=7;j++){
if(map[i][j]){
if(i+1<=5&&map[i+1][j]!=map[i][j]){//右移 右边可以为空 也可以为其他数
move(i,j,1);
ans[x][1]=i-1;ans[x][2]=j-1;ans[x][3]=1;
dfs(x+1);
for(int qiq=1;qiq<=5;qiq++)
for(int qjq=1;qjq<=7;qjq++)
map[qiq][qjq]=cf[x][qiq][qjq];
/*ans[x][1]=-1;ans[x][2]=-1;ans[x][3]=-1;//似乎可以不用*/
/*
移动 标记 更新 然后继续 下一步 移动 标记 更新 如果return 了 就开始回复 到移动之前
*/
}
if(i-1>=1&&!map[i-1][j]){//左移 只能是左边没有数
move(i,j,-1);
ans[x][1]=i-1;ans[x][2]=j-1;ans[x][3]=-1;
dfs(x+1);
for(int qaq=1;qaq<=5;qaq++)
for(int qwq=1;qwq<=7;qwq++)
map[qaq][qwq]=cf[x][qaq][qwq];
}
/*
因为 左右移动都可以 移动到空白位置 然后下降,但是 如果 左移或者右移 左右有数,则会重复 ,所以留一个右移就好了
*/
}
}
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=5;i++){
for(int j=1;j<=8;j++){
scanf("%d",&js);
if(js==0)break;
map[i][j]=js;
}
}
dfs(1);
printf("-1");
return 0;
}