P1312 Mayan游戏
毒瘤模拟爆搜题。。。
题意:
Mayan puzzle
是最近流行起来的一个游戏。游戏界面是一个 7 行 5 列的棋盘,上面堆放着一些方块,
方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上。游戏通关是指在规定的步数内消除所有的方块,消除方块的规则如下:
1 、每步移动可以且仅可以沿横向(即向左或向右)拖动某一方块一格:当拖动这一方块时,如果拖动后到达的位置(以下称目标位置)也有方块,那么这两个方块将交换位置;
如果目标位置上没有方块,那么被拖动的方块将从原来的竖列中抽出,并从目标位置上掉落(直到不悬空,参见下面图1 和图2);
2 、任一时刻,如果在一横行或者竖列上有连续三个或者三个以上相同颜色的方块,则它们将立即被消除(参见图1 到图3)。
注意:
a) 如果同时有多组方块满足消除条件,几组方块会同时被消除(例如图 4 ,三个颜色为 1 的方块和三个颜色为 2 的方块会同时被消除,最后剩下一个颜色为 2 的方块)。
b) 当出现行和列都满足消除条件且行列共享某个方块时,行和列上满足消除条件的所有方块会被同时消除(例如下面图5 所示的情形,5 个方块会同时被消除)。
3 、方块消除之后,消除位置之上的方块将掉落,掉落后可能会引起新的方块消除。注意:掉落的过程中将不会有方块的消除。
上面图1 到图 3 给出了在棋盘上移动一块方块之后棋盘的变化。棋盘的左下角方块的坐标为(0, 0 ),将位于(3, 3 )的方块向左移动之后,游戏界面从图 1 变成图 2 所示的状态,
此时在一竖列上有连续三块颜色为4 的方块,满足消除条件,消除连续3 块颜色为4 的方块后,上方的颜色为3 的方块掉落,形成图 3 所示的局面。
搜索时每次复制一份进行操作
剪枝:
1、两个颜色相同的不用交换
2、若左右均有块,只考虑左边向右走(字典序最小)
注意:每次交换都要考虑掉落的情况,对于消除,枚举中间点(三连)扫一遍标记,消除并处理掉落
因为消了一次就可能有下一次,继续,知道无法消为止
del(now) 把当前状态能消的全消,并处理掉落的情况
down(now,i,j)前提:(i,j)这一格为空
作用:把i,j正上方的整体向下移动一格
#include<cstdio> #include<iostream> #include<cstring> #include<cctype> using namespace std; #define _ 0 #define love_nmr 0 #define olinr return int n; int rx[3]={0,1,-1}; bool vis[10][10]; struct wmy { int mp[10][10]; void copy(wmy &y) { for(int i=0;i<=4;i++) for(int j=0;j<=6;j++) mp[i][j]=y.mp[i][j]; } bool pd() { for(int i=0;i<=4;i++) if(mp[i][0])return false; return true; } void out() { for(int i=0;i<=6;i++) { for(int j=0;j<=4;j++) printf("%d ",mp[j][i]); putchar('\n'); } } }cs; struct node { int x,y,dir; }ans[10]; int tp[20]; inline void print() { for(int i=1;i<=n;i++) cout<<ans[i].x<<" "<<ans[i].y<<" "<<ans[i].dir<<endl; } inline void swap(int &x,int &y) { int t=x; x=y; y=t; } inline void down(wmy &now,int x,int y) { int t=y+1; while(now.mp[x][t]) { now.mp[x][y]=now.mp[x][t]; now.mp[x][t]=0; t++; y++; } } inline void del(wmy &now) { bool flag=false; for(int i=0;i<=4;i++) for(int j=0;j<=6;j++) { if(!now.mp[i][j]) continue; int color=now.mp[i][j]; if(i-1>=0&&i+1<=4&&now.mp[i-1][j]==color&&now.mp[i+1][j]==color) { vis[i-1][j]=true; vis[i+1][j]=true; vis[i][j]=true; } if(j-1>=0&&j+1<=6&&now.mp[i][j-1]==color&&now.mp[i][j+1]==color) { vis[i][j+1]=true; vis[i][j-1]=true; vis[i][j]=true; } } for(int i=0;i<=4;i++) for(int j=6;j>=0;j--) { if(vis[i][j]) { now.mp[i][j]=0; down(now,i,j); vis[i][j]=false; flag=true; } } if(flag) del(now); } inline void dfs(wmy now,int step) { if(step==n+1) { if(now.pd()) { print(); exit(love_nmr); } return; } for(int i=0;i<=4;i++) { for(int j=0;j<=6;j++) { if(now.mp[i][j]) { for(int k=1;k<=2;k++) { wmy ls; ls.copy(now); int xx=i+rx[k]; int yy=j; if(xx>=0&&xx<=4) { if(ls.mp[i][j]==ls.mp[xx][yy]) continue; if(k==2&&ls.mp[xx][yy])continue; if(!ls.mp[xx][yy]) { swap(ls.mp[i][j],ls.mp[xx][yy]); down(ls,i,j); for(int o=yy-1;o>=0;o--) if(!ls.mp[xx][o]) down(ls,xx,o); else break; del(ls); } else { swap(ls.mp[i][j],ls.mp[xx][yy]); del(ls); } ans[step].x=i; ans[step].y=j; ans[step].dir=rx[k]; dfs(ls,step+1); ans[step].x=0; ans[step].y=0; ans[step].dir=0; } } } } } } inline int read() { int x=0,f=1; char ch=getchar(); while(!isdigit(ch)) { if(ch=='-') f=-f; ch=getchar(); } while(isdigit(ch)) { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } return x*f; } int main() { n=read(); for(int i=0;i<=4;i++) { for(int j=0;j<=7;j++) { cs.mp[i][j]=read(); if(cs.mp[i][j]==0) break; tp[cs.mp[i][j]]++; } } for(int i=1;i<=15;i++) if(tp[i]&&tp[i]<3) { cout<<-1; olinr ~~(0^_^0)+love_nmr; } dfs(cs,1); cout<<-1; olinr ~~(0^_^0)+love_nmr; }