#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真题代码注释 > 正文
有话要说...