[COGS 622] [NOIP2011] 玛雅游戏 模拟
整个模拟的关键除了打出来就是一个剪枝:对于两个左右相邻的块你不用再走←,因为走→是等效的
#include<cstdio> #include<cstring> #include<cstdlib> #include<ctime> #define r register using namespace std; int f[20][20][20]; int s[20][20]; bool die[20][20]; int n; bool god; inline void Init() { scanf("%d",&n); for(int i=1,x;i<=5;i++) while(1) { scanf("%d",&x); if(x==0)break; f[0][i][++f[0][i][0]]=x; } } void arrange(int h,int x,int y,int t) { s[h][1]=x; s[h][2]=y; s[h][3]=t; memcpy(f[h],f[h-1],sizeof(f[h])); f[h][x][y]^=f[h][x+t][y]^=f[h][x][y]^=f[h][x+t][y]; if(!f[h][x][y])++f[h][x+t][0],--f[h][x][0]; if(f[h][x][y]==0&&f[h][x][y+1]!=0) { r int j=y+1; while(f[h][x][j]!=0) f[h][x][j-1]^=f[h][x][j]^=f[h][x][j-1]^=f[h][x][j],++j; } if(f[h][x+t][y-1]==0) { r int j=y-1; while(f[h][x+t][j]==0) f[h][x+t][j]^=f[h][x+t][j+1]^=f[h][x+t][j]^=f[h][x+t][j+1],--j; } r int get; do { get=0; for(r int i=1;i<=5;++i) for(r int j=1;j<=f[h][i][0];++j) { r int k=0; while(f[h][i][j]==f[h][i][j+k])++k; if(k>=3) { for(int l=0;l<k;++l) die[i][j+l]=1; } j+=k-1; } for(r int i=1;i<=7;++i) for(r int j=1;j<=5;++j) { if(f[h][j][i]==0)continue; r int k=0; while(f[h][j][i]==f[h][j+k][i])++k; if(k>=3) { for(int l=0;l<k;l++) die[j+l][i]=1; } j+=k-1; } for(r int i=1;i<=5;++i) for(r int j=1;j<=f[h][i][0];++j) if(die[i][j]) f[h][i][j]=0,die[i][j]=0; for(r int i=1;i<=5;++i) { r int k=0; for(r int j=1;j<=f[h][i][0];++j) if(f[h][i][j])f[h][i][++k]=f[h][i][j]; else ++get; for(r int j=k+1;j<=f[h][i][0];++j)f[h][i][j]=0; f[h][i][0]=k; } }while(get); } void dfs(int x) { if(x==n) { r int sum=0; for(r int i=1;i<=5;++i)sum+=f[x][i][0]; if(sum==0)god=1; return; } for(r int i=1;i<=5;i++) for(r int j=1;j<=f[x][i][0];j++) { if(i!=5) { arrange(x+1,i,j,1); dfs(x+1); if(god)return; } if(i!=1&&f[x][i-1][j]==0) { arrange(x+1,i,j,-1); dfs(x+1); if(god)return; } } } inline void work() { dfs(0); if(god) { for(int i=1;i<=n;i++) printf("%d %d %d ",s[i][1]-1,s[i][2]-1,s[i][3]); } else printf("-1"); } int main() { Init(); work(); return 0; }