请复制到编译器更好食用. !! 原始代码来自时间榜单第一的 牛客67700244号
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int N;
int path[7][4];//操作左为操作步数,右中1 2 3下标分别为 //横坐标 //纵坐标 //操作
struct node{//图形结构体内含方法
int mp[6][8],h[6];//mp为图形数组 //h数组表示为各方块列的高度
//方法1.判断数组是否清空
inline bool clear(){
bool pan=true;
for(int i=1;i<=5;i++){
if(h[i]!=0) { pan=false;break; } //未全部清除
}
return pan;
}
//方法2 方块的移动
inline void move(int x,int y,int op){//x,y为坐标 op为操作情况
//由于整个图形在数组中是 侧倒状态 op=1 即 x坐标下移 ; op=-1 x坐标上移
//判断方块移动位置是否为空
if(h[op+x]<y){//方块所移的目标位置的高度 小于 当前方块高度
//换句话说 方块会掉下去
h[op+x]++;//目标位置高度加一//也为方块高度
mp[op+x][h[op+x]]=mp[x][y]; //方块的转移
//之前位置方块的掉落
for(int i=y;i<=h[x]-1;i++) mp[x][i]=mp[x][i+1];
//假设 1 2 3 0 4 5 //那么i的范围 1 2 3 [0 4] 5 //0处赋值为 4; 4 处赋值为 5 //变成1 2 3 4 5 '5'
h[x]--;//保证后续遍历不会计算到 '5'
}
else swap(mp[x][y],mp[x+op][y]);//交换位置方块都存在直接交换
}
//方法3 方块消除单次方法(同行或同列有三个或以上 同色方块 //标记->删除->掉落
inline bool once_clean(){
bool flag=false,vis[6][8];//flag用于判断 是否存在 可消除的方块组//vis 标记可消去方块的坐标位置
memset(vis,false,sizeof(vis));
//侧倒后图形的 横向和纵向 的遍历(就是数组 行和列 的遍历)
//1.横向判断以及标记
for(int i=1;i<=5;i++){//!!!!!j++
for(int j=2;j<=h[i]-1;j++){//例:i行各方块为 1 1 1 2 3 4 //h[i]==6// j的范围 1 [1 1 2 3] 4//
if(mp[i][j-1]==mp[i][j]&&mp[i][j]==mp[i][j+1]){
flag=true;//存在可消除方块组
vis[i][j-1]=vis[i][j]=vis[i][j+1]=true;//标记可消除方块组
}
}
}
//2.纵向判断即标记
for(int i=2;i<=4;i++){
int min_h=min(h[i-1],min(h[i],h[i+1]));//取 相邻三行的最短高度
for(int j=1;j<=min_h;j++){
if(mp[i-1][j]==mp[i][j]&&mp[i][j]==mp[i+1][j]){
flag=true;
vis[i-1][j]=vis[i][j]=vis[i+1][j]=true;//!!!!vis//非mp
}
}
}
//
if(!flag) return false;//后续不再进行该方法 once_clean()方法
//清除和掉落操作
for(int i=1;i<=5;i++){
int t=0;//当前i行的实际长度 //方块实际高度
for(int j=1;j<=h[i];j++){
if(!vis[i][j]){
mp[i][++t]=mp[i][j];
if(t!=j) mp[i][j]=0;//方块原位置清除
}
else mp[i][j]=0;//!!!!!!!!!!
}//!!h[i]=t;的位置放错
h[i]=t;//消去方块后新高
}
return true;//也是当前 flag的值
}
//
inline void clean_all(){
while(once_clean());//如果可消除 就在一次消除后 继续判断是否消除
}
}Mayan;//原始图形
void dfs(node now,int step){
//方法截止条件(一般放方法前面)
if(step==N){
if(now.clear()){
for(int i=0;i<step;i++) printf("%d %d %d\n",path[i][1]-1,path[i][2]-1,path[i][3]);
exit(0);//程序结束
}
return ;
}
//对当前图形进行深度搜索//!!!就是把可以操作的都操作一遍,
for(int i=1;i<=5;i++){
for(int j=1;j<=now.h[i];j++){
//考虑字典序大小 先考虑右移
if(i!=5){//前四行考虑只考虑方块下移//也就是原图形中的左边四排考虑右移
if(now.mp[i][j]!=now.mp[i+1][j]){//两方块的数值不一样,
//1.两个位置方块存在,但颜色不一样 2.当前位置有方块, 所转移目标位置没方块
node nxt;//下一图形
nxt=now;//该赋值可以更容易理解图形的回溯
nxt.move(i,j,1);//
nxt.clean_all();
path[step][1]=i,path[step][2]=j,path[step][3]=1;
//对新图像操作
dfs(nxt,step+1);
}
}
if(i!=1){
if(!now.mp[i-1][j]){//只有左边为空才左移
node nxt;//下一图形
nxt=now;//
nxt.move(i,j,-1);//]
nxt.clean_all();
path[step][1]=i,path[step][2]=j,path[step][3]=-1;
//对新图像操作
dfs(nxt,step+1);
}
}
}
}
return ;
}
inline int read()
{
int ret=0,ff=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') ff=-ff;ch=getchar();}
while(isdigit(ch)){ret=(ret<<3)+(ret<<1)+(ch^48);ch=getchar();}
return ret*ff;
}
int main() {
N=read();//操作数
for(int i=1;i<=5;i++) {
int t,j=0;
while(t=read(),t) Mayan.mp[i][++j]=t;
Mayan.h[i]=j;
}
dfs(Mayan,0);//当前图像Mayan,执行第0+1步操作
printf("-1");//如果dfs方法中使用过后,程序未结束,表示不可能全部消除
return 0;
}