题目链接:https://www.luogu.org/problemnew/show/P1312

我的第一篇题解!!

当然感谢ZAGER 的提示,他的链接https://www.cnblogs.com/ZAGER/p/9535526.html

这道题是一个大暴搜,真实考验了我的代码能力……

写函数是个好习惯,思路清晰明了。

分步骤

定义map[i][j]表示当前地图的情况,last[x][i][j]表示第x步时地图原貌,ans[x][i]记录第x步时的操作

check()检查是否被消完,当然根据规则只要检查最下面一行是否都被消完即可;

bool check()
{
for(int i=;i<=;i++)
{
if(map[i][]) return ;
}
return ;
}

update()进行掉落过程,我们从下往上搜,记录当前map有值的时候其下面有几个空行

void update()//掉落过程
{
for(int i=;i<=;i++)
{
int down=;
for(int j=;j<=;j++)
{
if(!map[i][j]) down++;
else
{
if(!down) continue;
map[i][j-down]=map[i][j];
map[i][j]=;
}
}
}
}

重点在这(对于我来说)

转换移动的操作,没好好看题,移动的时候不一定只和其他方块互换,也可以拖到悬空,然后掉落,所以互换后要检查掉落情况

void move(int x,int y,int z)//转换移动
{
int mem=map[x][y];
map[x][y]=map[x+z][y];
map[x+z][y]=mem;
update();
while(remove()) update();//被消除后进行掉落
}

remove()用来进行消除过程。为了满足条件图5情况,我们先记录在进行消除。

int remove()//消除过程
{
bool flag=;
for(int i=;i<=;i++)
{
for(int j=;j<=;j++)
{
if(i>=&&i<=&&map[i][j]&&map[i][j]==map[i-][j]&&map[i][j]==map[i+][j])
{
xx[i-][j]=;xx[i][j]=;xx[i+][j]=;flag=;
}
if(j>=&&j<=&&map[i][j]&&map[i][j]==map[i][j+]&&map[i][j]==map[i][j-])
{
xx[i][j]=;xx[i][j-]=;xx[i][j+]=;flag=;
}
}
}//先记录再消除,满足图五情况
if(!flag) return ;
for(int i=;i<=;i++)
{
for(int j=;j<=;j++)
{
if(xx[i][j])
{
map[i][j]=;
xx[i][j]=;
}
}
}
return ;
}

还有几个无关紧要(也很重要)的小函数,代码里有注解

还有一个重要的剪枝,就是“向左的时候如果左方并非是空,则跳过(否则可以选择其左侧方块右移,这样字典序更小)”;

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; int n;
int map[][],last[][][],ans[][];//map当前地图,;last第几步移动前的地图;ans是前为步数,后为答案
int xx[][];
bool check()
{
for(int i=;i<=;i++)
{
if(map[i][]) return ;
}
return ;
} void memory(int x)
{
for(int i=;i<=;i++)
{
for(int j=;j<=;j++)
{
last[x][i][j]=map[i][j];//记录第x步时地图的原貌
}
}
} void update()//掉落过程
{
for(int i=;i<=;i++)
{
int down=;
for(int j=;j<=;j++)
{
if(!map[i][j]) down++;
else
{
if(!down) continue;
map[i][j-down]=map[i][j];
map[i][j]=;
}
}
}
} int remove()//消除过程
{
bool flag=;
for(int i=;i<=;i++)
{
for(int j=;j<=;j++)
{
if(i>=&&i<=&&map[i][j]&&map[i][j]==map[i-][j]&&map[i][j]==map[i+][j])
{
xx[i-][j]=;xx[i][j]=;xx[i+][j]=;flag=;
}
if(j>=&&j<=&&map[i][j]&&map[i][j]==map[i][j+]&&map[i][j]==map[i][j-])
{
xx[i][j]=;xx[i][j-]=;xx[i][j+]=;flag=;
}
}
}//先记录再消除,满足图五情况
if(!flag) return ;
for(int i=;i<=;i++)
{
for(int j=;j<=;j++)
{
if(xx[i][j])
{
map[i][j]=;
xx[i][j]=;
}
}
}
return ;
}
void move(int x,int y,int z)//转换移动
{
int mem=map[x][y];
map[x][y]=map[x+z][y];
map[x+z][y]=mem;
update();
while(remove()) update();//被消除后进行掉落
} void recover(int x)
{
for(int i=;i<=;i++)
{
for(int j=;j<=;j++)
{
map[i][j]=last[x][i][j];
}
}
ans[x][]=;ans[x][]=;ans[x][]=;
}
void dfs(int x)
{
if(check())
{
for(int i=;i<=n;i++)
{
if(i!=) printf("\n");
for(int j=;j<=;j++)
{
printf("%d ",ans[i][j]);
}
}
exit();
}
if(x==n+) return ;
memory(x);
for(int i=;i<=;i++)
{
for(int j=;j<=;j++)
{
if(map[i][j])
{
if(i<=&&map[i][j]!=map[i+][j])
{
move(i,j,);
ans[x][]=i-;ans[x][]=j-;ans[x][]=;
dfs(x+);
recover(x);//恢复原地图和ans
}
}
if(i>=&&(!map[i-][j]))
{
move(i,j,-);
ans[x][]=i-;ans[x][]=j-;ans[x][]=-;
dfs(x+);
recover(x);
}
}
} } int main()
{
scanf("%d",&n);
for(int i=;i<=;i++)
{
for(int j=;j<=;j++)
{
int x;
scanf("%d",&x);
if(x==) break;
map[i][j]=x;
}
}
dfs();//从第一步开始搜
printf("-1\n");
return ;
}

NOIP 2011 Mayan游戏 大暴搜的更多相关文章

  1. [NOIp 2011]Mayan游戏

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

  2. NOIp 2011 mayan游戏 搜索

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

  3. 洛谷 P1312 [ NOIP 2011 ] Mayan游戏 —— 搜索+模拟

    题目:https://www.luogu.org/problemnew/show/P1312 还是不擅长这种题,所以参考了一下TJ: 其实也很好搜,按字典序,先搜右移,再搜左移: 不交换相同颜色的两个 ...

  4. noip提高组2011 Mayan游戏

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

  5. 【Luogu】P1312Mayan游戏(暴搜)

    题目链接 由于是暴搜题,所以这篇博客只讲怎么优化剪枝,以及一些细节. 模拟消除思路:因为消除可以拆分成小的横条或竖条,而这些条的长度至少为三,所以一块可消除的区域至少会有一个中心点.这里的中心点可以不 ...

  6. ⌈洛谷1312⌋⌈NOIP提高组2011⌋Mayan游戏【搜索】

    感想 真的,感觉这道题目好坑爹,我这个蒟蒻调了好几个世纪才调出来. 重构代码千万遍,依旧只有-1输出. 正解 非常明显的一道搜索题目. 每一次记录上一级的状态,这样实现比较不容易出错. 然后考虑剪枝: ...

  7. BZOJ 1193 [HNOI2006]马步距离:大范围贪心 小范围暴搜

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1193 题意: 给定起点(px,py).终点(sx,sy).(x,y < 100000 ...

  8. 【2019.7.20 NOIP模拟赛 T1】A(A)(暴搜)

    打表+暴搜 这道题目,显然是需要打表的,不过打表的方式可以有很多. 我是打了两个表,分别表示每个数字所需的火柴棒根数以及从一个数字到另一个数字,除了需要去除或加入的火柴棒外,至少需要几根火柴棒. 然后 ...

  9. NOIP 2011 Day 1

    NOIP 2011 Day 1 tags: NOIP 搜索 categories: 信息学竞赛 总结 铺地毯 选择客栈 Mayan游戏 铺地毯 Solution 因为只会询问一个点被谁覆盖, 而且后面 ...

随机推荐

  1. 创建Tensor

    目录 创建Tensor numpy, list numpy list zeros, ones, fill zeros ones fill random 打乱idx后,a和b的索引不变 constant ...

  2. C语言学习4

    C/C++语言五大内存分区:堆.栈.自由存储区.全局/静态存储区和常量存储区 栈:就是那些由编译器在需要的时候分配,在不需要的时候自动清楚的存储区,里面的变量通常是全局变量.函数参数等. 堆:就是那些 ...

  3. Python操作Redis、Memcache

       今天主要介绍如何通过python来对Redis和memcache进行操作,下面开始今天的内容: 一.Memcached操作 Memcached是一个高性能的分布式内存对象缓存系统,用于动态Web ...

  4. 圆角计算 Shader

    圆角的计算 在Shader中,我们使用UV坐标来计算需要显示的部分和不需要显示的部分,使用透明来处理显示与不显示.UV坐标如下图1,我们将坐标平移到图2位置,面片的UV坐标原点在面片中心,UV坐标范围 ...

  5. 【20】AngularJS 参考手册

    AngularJS 参考手册 AngularJS 指令 用到的 AngularJS 指令 : 指令 描述 解析 ng-app 定义应用程序的根元素. 指令 ng-bind 绑定 HTML 元素到应用程 ...

  6. jQuery学习之------选择器

    a.id选择器 <div id=”test1”></div> var div1=$(“#test1”);                //同css的写法一样id选择器用#号实 ...

  7. [K/3Cloud] 创建一个单据转换插件

    概念: 创建一个业务单据转换插件,在单据转换的各个时点干预单据转换的相关逻辑控制. 示例: 新建一个类,继承自单据转换插件基类Kingdee.BOS.Core.Metadata.ConvertElem ...

  8. [NOIP2005] 普及组 循环

    陶陶摘苹果 校门外的树 采药 以上三道都不是重点 循环 题目描述 乐乐是一个聪明而又勤奋好学的孩子.他总喜欢探求事物的规律.一天,他突然对数的正整数次幂产生了兴趣. 众所周知,2的正整数次幂最后一位数 ...

  9. 【HDOJ6146】Pokémon GO(DP,计数)

    题意:一个2*n的矩阵,从任意一格出发,不重复且不遗漏地走遍所有格子,问方案数 mo 10^9+7 n<=10000 思路:因为OEIS搜出来的两个数列都是错误的,所以考虑DP 设B[i]为2* ...

  10. Codeforces915F. Imbalance Value of a Tree

    n<=1e6的树问所有路径的极差之和. 被遗忘的套路...以后绝对不会再忘了QAQ 只要算最大值之和即可,最小值同理.数字从大到小排序(反正都是要排序的,如果从大到小不行等会反过来试试),然后逐 ...