题目:洛谷P1312、Vijos P1738、codevs1136。
题目大意:在一个7行5列的棋盘(左下角坐标0,0)上,有一些不同颜色的棋子。
规定某一时刻,连续三个横排或竖列的棋子颜色相同,则它们被消掉(同时满足条件的一起消掉,存在多个这样的情况有公共棋子时,所有的都消掉)。
然后有一种操作:
将一个棋子往左/右移动或和左边/右边的棋子交换。(左为-1,右为1)
规定棋盘上没有棋子时,游戏胜利。
现在给出顺时针旋转$90^\circ$后的棋盘,你要进行恰好n次操作,使游戏胜利,输出字典序最小(横坐标最小,然后纵坐标最小,然后方向最小,1比-1小)的操作方案。
如果不可能,输出-1。
解题思路:看到这么小的数据范围($n\leq 5$),肯定想到暴搜,而好像也没有别的方法。
题目要求字典序最小,那我们就按字典序最小的方案搜,找到就输出结束程序。
这里有一些剪枝:
①当一种颜色的个数为1或2时,一定不可能胜利,跳出。
②搜的时候,先搜往右的,如果当前棋子和右边棋子颜色相同,就不搜。
③搜左边时,只考虑左边为空的情况,如果不为空,则等价于左边的棋子向右交换的操作,字典序更小,因此一定不可能为答案。
消除的情况,可以枚举中间点,然后判断三个是否相同即可。
掉下来的情况,暴力移动即可。
剩下的,只需注意状态的保存和还原就行了。
别的没什么技巧可言。
C++ Code:
#include<cstdio> #include<cstring> #include<cstdlib> int n; int bl[9][9],tong[12]={0},ansx[7],ansy[7],yd[7]; bool bj[9][9]; void clean(){ bool hasqc=true; while(hasqc){ hasqc=false; bool dxl=true; while(dxl){ dxl=false; for(int i=0;i<5;++i) for(int j=0;j<8;++j) if(bl[i][j]==0&&bl[i][j+1]) bl[i][j]=bl[i][j+1],bl[i][j+1]=0,dxl=true; } memset(bj,0,sizeof bj); for(int i=0;i<5;++i) for(int j=0;j<8;++j){ if(i&&i<4&&bl[i][j]&&bl[i][j]==bl[i-1][j]&&bl[i][j]==bl[i+1][j]) bj[i][j]=bj[i-1][j]=bj[i+1][j]=hasqc=true; if(j&&bl[i][j]&&bl[i][j]==bl[i][j-1]&&bl[i][j]==bl[i][j+1]) bj[i][j]=bj[i][j-1]=bj[i][j+1]=hasqc=true; } if(hasqc){ for(int i=0;i<5;++i) for(int j=0;j<8;++j) if(bj[i][j])--tong[bl[i][j]],bl[i][j]=0; } } } void dfs(int now){ if(now>n){ for(int i=0;i<12;++i) if(tong[i])return; for(int i=1;i<=n;++i) printf("%d %d %d\n",ansx[i],ansy[i],yd[i]); exit(0); } for(int i=0;i<12;++i) if(tong[i]&&tong[i]<3)return; int ylzt[9][9],yltong[12]; for(int i=0;i<9;++i)for(int j=0;j<9;++j) ylzt[i][j]=bl[i][j]; memcpy(yltong,tong,sizeof tong); for(int i=0;i<5;++i){ for(int j=0;j<8;++j) if(ylzt[i][j]){ if(i<4&&ylzt[i+1][j]!=ylzt[i][j]){ memcpy(tong,yltong,sizeof tong); for(int i=0;i<9;++i)for(int j=0;j<9;++j) bl[i][j]=ylzt[i][j]; int x=bl[i][j]; bl[i][j]=bl[i+1][j]; bl[i+1][j]=x; ansx[now]=i,ansy[now]=j,yd[now]=1; clean(); dfs(now+1); } if(i&&!ylzt[i-1][j]){ memcpy(tong,yltong,sizeof tong); for(int i=0;i<9;++i)for(int j=0;j<9;++j) bl[i][j]=ylzt[i][j]; bl[i-1][j]=bl[i][j]; bl[i][j]=0; ansx[now]=i,ansy[now]=j,yd[now]=-1; clean(); dfs(now+1); } } } for(int i=0;i<9;++i)for(int j=0;j<9;++j) bl[i][j]=ylzt[i][j]; memcpy(tong,yltong,sizeof tong); } int main(){ scanf("%d",&n); for(int i=0;i<5;++i){ int t; scanf("%d",&t); for(int j=0;t;++j){ bl[i][j]=t; ++tong[t]; scanf("%d",&t); } } dfs(1); puts("-1"); return 0; }