闲的没事干,出来写一下早两天刷的一道搜索题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]玛雅游戏的更多相关文章

  1. NOIP2011玛雅游戏

    闲的没事干,出来写一下早两天刷的一道搜索题NOIP2011玛雅游戏,其实这道题还是比较水的,虽然看起来可能有点复杂. 方法很简单粗暴,直接根据规则模拟就行. 话不多说直接上代码(关键操作在注释中有提到 ...

  2. noip2011 玛雅游戏 大模拟

    深搜+模拟 需要剪枝:同一移动向右移了就不需要向左移了 #include<cstdio> #include<cstring> #include<iostream> ...

  3. [COGS 622] [NOIP2011] 玛雅游戏 模拟

    整个模拟的关键除了打出来就是一个剪枝:对于两个左右相邻的块你不用再走←,因为走→是等效的 #include<cstdio> #include<cstring> #include ...

  4. Luogu 1312 【NOIP2011】玛雅游戏 (搜索)

    Luogu 1312 [NOIP2011]玛雅游戏 (搜索) Description Mayan puzzle 是最近流行起来的一个游戏.游戏界面是一个7行5列的棋盘,上面堆放着一些方块,方块不能悬空 ...

  5. 玛雅游戏[NOIP2011]

    题目描述 Mayan puzzle 是最近流行起来的一个游戏.游戏界面是一个7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.游戏通关是指在规定 ...

  6. [NOIP2011] mayan游戏(搜索+剪枝)

    题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.游戏通关是指在规定 ...

  7. [NOIP2011]Mayan游戏 题解

    题目大意: 有一个5*7的方格,上面有几种颜色的方块,如果在一横行或者竖列上有连续三个或者三个以上相同颜色的方块,则它们将立即被消除,方块消除之后,消除位置之上的方块将掉落.每步移动可以且仅可以沿横向 ...

  8. NOIP2011 Mayan游戏

    3 Mayan游戏 题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上 ...

  9. Noip2011 Mayan游戏 搜索 + 模拟 + 剪枝

    写了一下午,终于AC了. 由于n<=5, 所以不需要太多的剪枝和技巧也能过.可以将操作后的消方块和下落和剪枝函数写到一个结构体中,这样会减少调试难度,更加简洁. 可以采用如下剪枝: 1. 如果当 ...

随机推荐

  1. Vue2.0原理-模板解析

    下面这段代码,vue内部做了什么操作?我去源码里面找找看 new Vue({ el: '#app' }) 入口 vue 的入口文件在 src/core/instance/index.js, 里面一进来 ...

  2. [面试]CVTE 2019提前批 Windows应用开发一面

    7.30接到面试电话问有没有时间进行一个20分钟左右的电话面试,不巧当时要去赶火车,就约到了两天后. 8.1还是同一个面试官打来电话 首先介绍项目吧,第一场面试,项目准备的也不怎么充分,讲了一个HAL ...

  3. 用 Delphi 7 实现基于 FFMS2 的视频转 GIF 工具 [原创]

    儿子经常要把自拍的视频(ts格式)转成表情包,下载了几个工具都不大好用,更多的还要收费.那就想自己写一个吧,没想到这一下断断续续地,居然 3 个月过去了.现在总算弄出个作品来了,结个贴吧.唉,天资愚钝 ...

  4. 【树莓派】crontab的两个问题

    1,/var/log下面,没有cron.log日志 root@raspberrypi:/# nano /etc/rsyslog.conf …… …… ############### #### RULE ...

  5. 黑客攻防web安全实战详解笔记

    如有不足,欢迎指出,谢谢! ----------------------------------------- 1,url传值 GET传值:其传递的值会附加到url上  POST传值:其传递的值不会加 ...

  6. Android NDK 工具链的使用方法(Standalone Toolchain)

    转载:http://blog.csdn.net/smfwuxiao/article/details/6587709 首先需要确定目标机器的指令集. 如果是 x86 的机器,用 x86-4.4.3 版本 ...

  7. 前端_JQuery

    使用参考:http://jquery.cuishifeng.cn/ 目录 jQuery是什么 jQuery对象 寻找元素(选择器和筛选器) 选择器 表单属性选择器 筛选器 操作元素(属性.css.文档 ...

  8. API验证

    API验证说明 API验证: a. 发令牌: 静态 PS: 隐患 key被别人获取 b. 动态令牌 PS: (问题越严重)用户生成的每个令牌被黑客获取到,都会破解 c. 高级版本 PS: 黑客网速快, ...

  9. Arduino IDE 安装esp8266 2.4.rc2的编译环境

    2.4. 版本, 有一个我需要的功能, 串口缓存, 可以修改. Serial.setRxBufferSize(1024); //修改为1024个字节. 安装步骤: 1. 需要FQ. 推荐用" ...

  10. 浅谈iOS内存管理机制

    iOS内存管理机制的原理是引用计数,引用计数简单来说就是统计一块内存的所有权,当这块内存被创建出来的时候,它的引用计数从0增加到1,表示有一个对象或指针持有这块内存,拥有这块内存的所有权,如果这时候有 ...