NOIP2011玛雅游戏
闲的没事干,出来写一下早两天刷的一道搜索题NOIP2011玛雅游戏,其实这道题还是比较水的,虽然看起来可能有点复杂。
方法很简单粗暴,直接根据规则模拟就行。
话不多说直接上代码(关键操作在注释中有提到):
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
#define ll long long
#define il inline
#define RG register
#define inf (1<<30)
using namespace std;
il int gi(){
RG int x=0,q=1; RG char ch=getchar();
while( ( ch<'0' || ch>'9' ) && ch!='-' ) ch=getchar();
if( ch=='-' ) q=-1,ch=getchar();
while(ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
return q*x;
}
int n,a,b;
int map[ 6 ][ 8 ],step[ 10 ][ 3 ];
bool broken[ 6 ][ 8 ],appear[ 11 ];
int color,sum[ 11 ];
il bool check(){
memset( sum,0,sizeof( sum ) );
for( RG int i=1;i<=5;i++ )
for( RG int j=1;j<=7;j++ )
sum[ map[ i ][ j ] ]++;
for( RG int i=1;i<=color;i++ )
if( sum[i] && sum[i]<=2 )
return false;
//若块数小于3则无法消去
return true;
}
il int count(){
memset( broken,0,sizeof( broken ) );
RG int left,right,top,bottom;
RG int ans=0,drop=0;
for( RG int i=1;i<=5;i++ )
for( RG int j=1;j<=7;j++ )
if( map[ i ][ j ] )
if( j==1 || ( j>1 && map[ i ][ j-1 ] ) ){//找到一个没有悬空的块
left=right=i;
top=bottom=j;
while(left>1 && map[left-1][j]==map[i][j])
left--;
while(right<4 && map[right+1][j]==map[i][j])
right++;
while(top<7 && map[ i ][top+1]==map[i][j])
top++;
while(bottom>1 && map[i][bottom-1]==map[i][j])
bottom--;
//统计可以消除的块
if( right-left+1>=3 )
for( RG int k=left;k<=right;k++ )
broken[ k ][ j ]=1;
if( top-bottom+1>=3 )
for( RG int k=top;k>=bottom;k-- )
broken[ i ][ k ]=1;
}
for( RG int i=1;i<=5;i++ )
for( RG int j=1;j<=7;j++ )
if( broken[ i ][ j ] )
ans++,map[ i ][ j ]=0;
RG int i,j,down,up;
for( i=1;i<=5;i++ ){
j=1;
while( j<=7&&map[ i ][ j ] ) j++;
down=j; //找到该列第一个空块
while( j<=7&&!map[ i ][ j ] )j++;
up=j-1;////找到该列最后一个空块
if( up==7 ) continue;//若道顶端都没有悬空的块就跳过该列
RG int k=0;
for( j=down;j<=7;j++ ){//下落操作
k++;
if( map[i][j] || !map[i][up+k] ) break;
map[i][j]=map[i][up+k];
map[i][up+k]=0;
drop=1;
}
}
//**下落的块还会造成其他块消除,所以再次统计**
if( drop ) ans+=count();
return ans;
}
il void dfs( int ste,int cnt ){//分别表示已走步数和剩余块数
if( !check() )return ;
if( ste>n ){
if( !cnt ){
for( RG int i=1;i<=n;i++ )
printf("%d %d %d \n",step[i][0]-1,step[i][1]-1,step[i][2]);
exit(0);
}
return ;
}
int mapp[ 6 ][ 8 ],if_change,x;
for( RG int i=1;i<=5;i++ )
for( RG int j=1;j<=7;j++ )
mapp[i][j]=map[i][j];
for( RG int i=1;i<=5;i++ )
for( RG int j=1;j<=7;j++ ){
if( map[i][j] ){//找到可以移动的块
if_change=1;
if( i<5 && map[i][j]!=map[i+1][j] ){
//考虑到结果的优先原则,先进行右移操作
swap( map[i][j],map[i+1][j] );
step[ste][0]=i;
step[ste][1]=j;
step[ste][2]=1;
x=cnt-count();
dfs( ste+1,x );
if_change=0;
}
if( !if_change ){//回溯
for( RG int g=1;g<=5;g++ )
for( RG int s=1;s<=7;s++ )
map[g][s]=mapp[g][s];
if_change=1;
}
if( i>1 && !map[i-1][j] ){
//只有左边没有块的时候才交换,否则就会和前面往右
//移的步骤重复
swap( map[i][j],map[i-1][j] );
step[ste][0]=i;
step[ste][1]=j;
step[ste][2]=-1;
x=cnt-count();
dfs( ste+1,x );
if_change=0;
}
if( !if_change )
for( RG int g=1;g<=5;g++ )
for( RG int s=1;s<=7;s++ )
map[ g ][ s ]=mapp[ g ][ s ];
}
}
}
il void init(){
n=gi();
for( RG int i=1;i<=5;i++ ){
RG int j=0;
a=gi();
while( a ){
map[ i ][ ++j ]=a;
if( !appear[ a ] ) appear[ a ]=1,color++;
a=gi();
b++;
}
}
}
int main(){init();dfs( 1,b );printf( "-1\n" );return 0;}
NOIP2011玛雅游戏的更多相关文章
- [NOIP2011]玛雅游戏
闲的没事干,出来写一下早两天刷的一道搜索题NOIP2011玛雅游戏,其实这道题还是比较水的,虽然看起来可能有点复杂. 方法很简单粗暴,直接根据规则模拟就行. 话不多说直接上代码(关键操作在注释中有提到 ...
- noip2011 玛雅游戏 大模拟
深搜+模拟 需要剪枝:同一移动向右移了就不需要向左移了 #include<cstdio> #include<cstring> #include<iostream> ...
- [COGS 622] [NOIP2011] 玛雅游戏 模拟
整个模拟的关键除了打出来就是一个剪枝:对于两个左右相邻的块你不用再走←,因为走→是等效的 #include<cstdio> #include<cstring> #include ...
- Luogu 1312 【NOIP2011】玛雅游戏 (搜索)
Luogu 1312 [NOIP2011]玛雅游戏 (搜索) Description Mayan puzzle 是最近流行起来的一个游戏.游戏界面是一个7行5列的棋盘,上面堆放着一些方块,方块不能悬空 ...
- 玛雅游戏[NOIP2011]
题目描述 Mayan puzzle 是最近流行起来的一个游戏.游戏界面是一个7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.游戏通关是指在规定 ...
- [NOIP2011] mayan游戏(搜索+剪枝)
题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.游戏通关是指在规定 ...
- [NOIP2011]Mayan游戏 题解
题目大意: 有一个5*7的方格,上面有几种颜色的方块,如果在一横行或者竖列上有连续三个或者三个以上相同颜色的方块,则它们将立即被消除,方块消除之后,消除位置之上的方块将掉落.每步移动可以且仅可以沿横向 ...
- NOIP2011 Mayan游戏
3 Mayan游戏 题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上 ...
- Noip2011 Mayan游戏 搜索 + 模拟 + 剪枝
写了一下午,终于AC了. 由于n<=5, 所以不需要太多的剪枝和技巧也能过.可以将操作后的消方块和下落和剪枝函数写到一个结构体中,这样会减少调试难度,更加简洁. 可以采用如下剪枝: 1. 如果当 ...
随机推荐
- 用php+mysql+ajax实现淘宝客服或阿里旺旺聊天功能 之 后台页面
在上一篇随笔中,我们已经看了如何实现前台的对话功能:前台我限定了店主只有一人,店铺只有一个,所有比较单一,但后台就不一样了,而后台更像是我们常见的聊天软件:当然,前台也应该实现这种效果,但原理懂了,可 ...
- [Linux] PHP程序员玩转Linux系列-腾讯云硬盘扩容挂载
1.PHP程序员玩转Linux系列-怎么安装使用CentOS 2.PHP程序员玩转Linux系列-lnmp环境的搭建 3.PHP程序员玩转Linux系列-搭建FTP代码开发环境 4.PHP程序员玩转L ...
- MongoDB--初始
指定启动目录,以服务形式启动 Mongod --dbpath=XXXXXX --logpath=XXXXXXXX --logappend --serviceName "XXXXX" ...
- TortoiseGit使用SSH
Windows TortoiseGit使用SSH连接 1 找到TortoiseGit自带的Puttygen工具 2.1 如果未生成过SSHKey,选择Generate(生成的过程中记得移动鼠标) 2. ...
- 耍一把codegen,这样算懂编译么?
最近使用protobuf搭了些服务器,对protobuf的机制略感兴趣,所以研究了下. 大致分析没有什么复杂的 1 对定义的结构体生成消息封包协议 2 对定义的rpc函数生成接口定义 3 用户按pro ...
- [leetcode-357-Count Numbers with Unique Digits]
Given a non-negative integer n, count all numbers with unique digits, x, where 0 ≤ x < 10n. Examp ...
- asp.net core 中灵活的配置方式
asp.net core支持外部文件和命令行参数方式来配置系统运行所需要的配置信息,我们从下面两个常用场景来具体说下具体使用方法. 一.监听地址及端口配置 1,命令行方式 asp.net core系统 ...
- Java内部类与final关键字详解
一.内部类的几种创建方法: 1.成员内部类 class Outer{ private int i = 1; class Inner{ public void fun() {System.out.pri ...
- Java多线程中join方法详解
join()方法用于让当前执行线程等待join线程执行结束.其实现原理是不停的检查join线程是否存活,如果join线程存活则让当前线程永远等待. join()方法部分实现细节 while(isAli ...
- maven(二) maven项目构建ssh工程(父工程与子模块的拆分与聚合)
前一节我们明白了maven是个什么玩意,这一节就来讲讲他的一个重要的应用场景,也就是通过maven将一个ssh项目分割为不同的几个部分独立开发,很重要,加油 --WH 一.maven父工程与子模块的拆 ...