【NOIP2011】玛雅游戏
来源:互联网 发布:2015网络十大神曲 编辑:程序博客网 时间:2024/06/05 16:32
题意
一个7行5列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上。游戏通关是指在规定的步数内消除所有的方块,消除方块的规则如下:
1.每步移动可以且仅可以沿横向(即向左或向右)拖动某一方块一格:当拖动这一方块时,如果拖动后到达的位置(以下称目标位置)也有方块,那么这两个方块将交换位置.如果目标位置上没有方块,那么被拖动的方块将从原来的竖列中抽出,并从目标位置上掉落
2.任一时刻,如果在一横行或者竖列上有连续三个或者三个以上相同颜色的方块,则它们将立即被消除。注意:
①.如果同时有多组方块满足消除条件,几组方块会同时被消除
②.当出现行和列都满足消除条件且行列共享某个方块时,行和列上满足消除条件的所有方块会被同时消除
3.方块消除之后,消除位置之上的方块将掉落,掉落后可能会引起新的方块消除。注意:掉落的过程中将不会有方块的消除
解法
搜索:
四条剪枝原则:
(1)交换两个颜色相同的块没有意义
(2)一个块的左边是非空块时不需要考虑左移,因为会和之前的块右移重复,即只有当左块为空时才左移
(3)根据题目优先度的排序,可以知道,右移优先于左移,所以在dfs时先考虑右移
(4)如果有一种颜色当前的块数目x满足1<=x<=2,则此情况不合法
然后直接进行搜索,注意上方悬空块的处理
复杂度
O(
不会算 )
代码
#include<iostream>#include<cstring>#include<cstdlib>#include<cstdio>#include<cmath>using namespace std;bool vis[10][10];bool flag[11];int map[10][10];int step[10][5];int count[11];int n,N;int del( )//计算这一次移动能够消去多少{ memset( vis,1,sizeof vis ); int res=0; int l,r,u,d,x,y,t; bool cs=0; for(int i=1;i<=5;i++) for(int j=1;j<=7;j++) if( map[ i ][ j ] ) if( ( j>=2 && map[ i ][ j-1 ] ) || j==1 )//寻找中心块来计算可以消除的块 { l=r=i; u=d=j; while( l>=2 && map[ l-1 ][ j ]==map[ i ][ j ] ) l--; while(r<4 && map[ r+1 ][ j ]==map[ i ][ j ] ) r++; while( d>=2 && map[ i ][ d-1 ]==map[ i ][ j ] ) d--; while( u<=6 && map[ i ][ u+1 ]==map[ i ][ j ] ) u++; if( r-l>=2 )//表示横方向上可以消除方块 for(int k=l;k<=r;k++) vis[ k ][ j ]=0; if( u-d>=2 )//表示竖方向上可以消除方块 for(int k=d;k<=u;k++) vis[ i ][ k ]=0; } for(int i=1;i<=5;i++) for(int j=1;j<=7;j++) if( !vis[ i ][ j ] )//可以消除 { res++; map[ i ][ j ]=0; } for(int i=1,j;i<=5;i++)//求每一列是否有块悬着 { for(j=1;j<=7;j++) if( !map[ i ][ j ] ) break; x=j;//找到第一个空块 for( ;j<=7;j++ ) if( map[ i ][ j ] ) break; if( j==8 )//如果一直到顶都是空块,就没有块可以掉下来,所以不用管它 continue; y=j-1;//找到空块范围的末端 t=0; for( j=x;j<=7;j++ )//悬着的块掉下来 { t++; if( !map[ i ][ y+t ] || map[ i ][ j ]) break; map[ i ][ j ]=map[ i ][ y+t ]; map[ i ][ y+t ]=0; cs=1; } } if( cs )//如果有掉下去的 res+=del( );//当悬着的块掉下去后可能还可以继续消除,所以再来一次del return res;}/* 很明显的剪枝: (1)交换两个颜色相同的块没有意义 (2)一个块的左边是非空块时不需要考虑左移,因为会和之前的块右移重复,即只有当左块为空时才左移 (3)根据题目优先度的排序,可以知道,右移优先于左移,所以在dfs时先考虑右移 (4)如果有一种颜色当前的块数目x满足1<=x<=2,则此情况不合法*/bool judge( ){ memset( count,0x0,sizeof count ); for(int i=1;i<=5;i++) for(int j=1;j<=7;j++) count[ map[ i ][ j ] ]++; for(int i=1;i<=N;i++) if( count[ i ]>=1 && count[ i ]<=2 ) return 0; return 1;}void dfs(int num,int tot){ if( !judge( ) ) return ; if( num>=n+1 ) { if( !tot )//因为在dfs时就考虑到了优先顺序,所以最先搜到的必定是优先级最大的 { for(int i=1;i<=n;i++) printf("%d %d %d\n",step[ i ][ 1 ]-1,step[ i ][ 2 ]-1,step[ i ][ 3 ] ); exit(0); } return ; } int x,y; int temp[10][10],p,q; bool cs; for(int i=1;i<=5;i++) for(int j=1;j<=7;j++) temp[ i ][ j ]=map[ i ][ j ]; for(int i=1;i<=5;i++) for(int j=1;j<=7;j++) { if( map[ i ][ j ] ) { cs=1; if( i<=4 &&map[ i ][ j ]!=map[ i+1 ][ j ] )//剪枝(1) { swap( map[ i ][ j ],map[ i+1 ][ j ] ); step[ num ][ 1 ]=i; step[ num ][ 2 ]=j; step[ num ][ 3 ]=1; p=tot-del(); dfs( num+1,p ); cs=0; } if( !cs ) { cs=1; for(p=1;p<=5;p++) for(q=1;q<=7;q++) map[ p ][ q ]=temp[ p ][ q ]; } if( i>=2 && !map[ i-1 ][ j ] )//剪枝(2) { swap( map[ i ][ j ],map[ i-1 ][ j ] ); step[ num ][ 1 ]=i; step[ num ][ 2 ]=j; step[ num ][ 3 ]=-1; p=tot-del(); dfs( num+1,p ); cs=0; } if( !cs ) for(p=1;p<=5;p++) for(q=1;q<=7;q++) map[ p ][ q ]=temp[ p ][ q ]; } }}int main(){ int x,y=0; scanf("%d",&n); for(int i=1,j;i<=5;i++) { j=0; scanf("%d",&x); while( x ) { map[ i ][ ++j ]=x; if( !flag[ x ] ) { flag[ x ]=1; N++; } y++; scanf("%d",&x); } } dfs( 1,y ); cout<<-1<<endl; return 0;}
- dfs NOIP2011] 玛雅游戏
- [NOIP2011] 玛雅游戏(回溯)
- [NOIP2011] 玛雅游戏
- 【NOIP2011】玛雅游戏
- noip2011 玛雅游戏 大模拟
- 【NOIP2013】Day1T3 玛雅游戏
- NOIP玛雅游戏
- [NOIP2011]Mayan游戏【搜索】
- NOIP2011 Mayan游戏(搜索)
- 【CodeVS1136】【NOIP2011】Mayan 游戏
- NOIP2011 Mayan游戏 题解
- 【NOIP2011】Mayan游戏 搜索
- NOIP2011 Mayan游戏
- NOIP2011【Mayan游戏】
- NOIP2011 Mayan游戏
- noip2011 Mayan游戏
- 【NOIP2011】【DFS】Mayan游戏
- 玛雅游戏!!!!(爆搜!!神代码题)
- Data truncation: Data too long for column 'xxxx' at row 1
- STL QUEUE
- 【NOIP2012DAY1】国王游戏
- C语言复习
- fabric v0.6 startup
- 【NOIP2011】玛雅游戏
- matlab根轨迹
- [ java swing derby开发pc应用 ] 从零到上线(四)
- 多项式的嵌套乘法代码实现
- css的几个重用属性
- 全栈者角度--form提交问题(工程下载)
- JAVA IO操作
- idea + maven 使用jedis 连接redis
- 高可用的一些思考和理解