#inclue<bits/stdc++.h>
#define ll long long
#define N 10
//快速读
int read()
{
int X=0,w=0; char ch=0;
while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
return w?-X:X;
}
int n,map[N][N],ans[N][5],last[N][N][N],xiao[N][N];
//map表示整个输入
//ans表示移动
//last[d][i][j]:第d步时在i行j列的原状态
void copy(int x){
for(int i=1;i<=5;i++)
for(int j=1;j<=7;j++)
last[x][i][j]=map[i][j];
}
//掉下去 x统计map[i][j]下面几个0
void update(){
for(int i=1;i<=5;i++){
int x=0;
for(int j=1;j<=7;j++){
if(!map[i][j])x++;
else{
map[i][j-x]=map[i][j];
map[i][j]=0;
}
}
}
}
//消掉
bool remove(){
int flag=0;
for(int i=1;i<=5;i++)
for(int j=1;j<=7;j++){
//同列3个
if(i-1>=1&&i+1<=5&&map[i][j]==map[i-1][j]&&map[i][j]==map[i+1][j]&&map[i][j]){
xiao[i-1][j]=1;xiao[i+1][j]=1;xiao[i][j]=1;flag=1;
}
//同行3个
if(j-1>=1&&j+1<=7&&map[i][j]==map[i][j+1]&&map[i][j]==map[i][j-1]&&map[i][j]){
xiao[i][j]=1;xiao[i][j+1]=1;xiao[i][j-1]=1;flag=1;
}
}
//没有可以消除的,返回
if(!flag)return 0;
//处理需要消除的,归0
for(int i=1;i<=5;i++)
for(int j=1;j<=7;j++)
if(xiao[i][j]){
xiao[i][j]=0; //归0
map[i][j]=0; //消除
}
return 1;
}
//检查判断第一行5列是否都为0,
//因为最后都掉下来了,所以就看第一行是否都消除了
bool check(){
for(int i=1;i<=5;i++)
if(map[i][1])return 0;
return 1;
}
//处理一次操作,向左 -1 或向右移动 +1
//交换两个位置的方块,移动后要update,和remove
void move(int i,int j,int x){
int tmp=map[i][j];
map[i][j]=map[i+x][j];
map[i+x][j]=tmp;
update(); //移动后看是否掉落
while(remove())update();//掉落后,看能否消除,消除后看是否掉落
}
void dfs(int x){
//如果已经全部消除,则输出结果
if(check()){
for(int i=1;i<=n;i++){
if(i!=1)printf("\n");
for(int j=1;j<=3;j++)
printf("%d ",ans[i][j]);
}
exit(0);
}
//超过n步,则剪枝
if(x==n+1)return;
//记录下第x步的原图状态
copy(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][j]!=map[i+1][j]){
move(i,j,1);
//ans记录下操作,i-1,j-1是因为题目下标从0开始的,
ans[x][1]=i-1;ans[x][2]=j-1;ans[x][3]=1;
//继续试操作
dfs(x+1);
for(int i=1;i<=5;i++)
for(int j=1;j<=7;j++)
map[i][j]=last[x][i][j];//恢复上一次操作时原图
ans[x][1]=-1;ans[x][2]=-1;ans[x][3]=-1;
}
//想左移动 ,左边是0的情况才左移,算是一种剪枝--
//上面右移包含了左边不是0的情况了。
if(i-1>=1&&map[i-1][j]==0){
move(i,j,-1);
//记录下i-1,j-1想左移动
ans[x][1]=i-1;ans[x][2]=j-1;ans[x][3]=-1;
//下一步操作
dfs(x+1);
for(int i=1;i<=5;i++)
for(int j=1;j<=7;j++)
map[i][j]=last[x][i][j];//恢复原状态
ans[x][1]=-1;ans[x][2]=-1;ans[x][3]=-1;
}
}
}
}
int main()
{
//读入n,表示要求游戏通关的步数
n=read();
//每两个整数之间用一个空格隔开,
//每行以一个00 结束,自下向上表示每竖列方块的颜色编号
//先列后行
for(int i=1;i<=5;i++){
for(int j=1;j<=8;j++){
int x=read();
if(x==0)break;
map[i][j]=x;
}
}
//输出n行,每行包含3个整数x,y,g表示一次移动
memset(ans,-1,sizeof(ans));
//从第一个开始搜搜
dfs(1);
//没有答案,则输出-1
puts("-1");
return 0;
}当前位置:首页 > NOIP真题代码注释 > 正文

有话要说...