NOIP 2011 Mayan游戏 大暴搜
题目链接: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游戏 大暴搜的更多相关文章
- [NOIp 2011]Mayan游戏
Description Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.游戏 ...
- NOIp 2011 mayan游戏 搜索
题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.游戏通关是指在规定 ...
- 洛谷 P1312 [ NOIP 2011 ] Mayan游戏 —— 搜索+模拟
题目:https://www.luogu.org/problemnew/show/P1312 还是不擅长这种题,所以参考了一下TJ: 其实也很好搜,按字典序,先搜右移,再搜左移: 不交换相同颜色的两个 ...
- noip提高组2011 Mayan游戏
Mayan游戏 描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个7行5列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.**游戏通关 ...
- 【Luogu】P1312Mayan游戏(暴搜)
题目链接 由于是暴搜题,所以这篇博客只讲怎么优化剪枝,以及一些细节. 模拟消除思路:因为消除可以拆分成小的横条或竖条,而这些条的长度至少为三,所以一块可消除的区域至少会有一个中心点.这里的中心点可以不 ...
- ⌈洛谷1312⌋⌈NOIP提高组2011⌋Mayan游戏【搜索】
感想 真的,感觉这道题目好坑爹,我这个蒟蒻调了好几个世纪才调出来. 重构代码千万遍,依旧只有-1输出. 正解 非常明显的一道搜索题目. 每一次记录上一级的状态,这样实现比较不容易出错. 然后考虑剪枝: ...
- BZOJ 1193 [HNOI2006]马步距离:大范围贪心 小范围暴搜
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1193 题意: 给定起点(px,py).终点(sx,sy).(x,y < 100000 ...
- 【2019.7.20 NOIP模拟赛 T1】A(A)(暴搜)
打表+暴搜 这道题目,显然是需要打表的,不过打表的方式可以有很多. 我是打了两个表,分别表示每个数字所需的火柴棒根数以及从一个数字到另一个数字,除了需要去除或加入的火柴棒外,至少需要几根火柴棒. 然后 ...
- NOIP 2011 Day 1
NOIP 2011 Day 1 tags: NOIP 搜索 categories: 信息学竞赛 总结 铺地毯 选择客栈 Mayan游戏 铺地毯 Solution 因为只会询问一个点被谁覆盖, 而且后面 ...
随机推荐
- 《深入浅出深度学习:原理剖析与python实践》第八章前馈神经网络(笔记)
8.1 生物神经元(BN)结构 1.人脑中有100亿-1000亿个神经元,每个神经元大约会和其他1万个神经元相连 2.细胞体:神经元的主体,细胞体=细胞核+细胞质+细胞膜,存在膜电位 3.树突:从细胞 ...
- <mongoose>……find与findOne的区别……//
mongoose中的 find 和 findOne 都是用来查找指定表的数据的 find指的是查找指定表的所有数据,返回的是数组 User.find().then((result)=>{ con ...
- Linux读取网卡流量脚本
#!/bin/bash #eval `date "+day=%d; month=%m; year=%Y; hour=%H; minute=%M second=%S"` #INSTF ...
- MTK android L使用汇顶TP如何使用B协议
使用B协议上报之前的代码: #include "tpd.h" #include "tpd_custom_gt9xx.h" #ifndef TPD_NO_GPIO ...
- restful(1):序列化
restful协议中,一切皆是资源,操作只是请求方式 model_to_dict()方法: from django.forms.models import model_to_dict obj = Pu ...
- [K/3Cloud] 理解BOS关于Enabled属性的表决器原理
通常的编程中,我们习惯: btnOK.Enabled = true; 这个样子就会将按钮变成有效,反之亦然.但在ERP的表单中,其某个按钮或字段其有效性及其复杂,例如一个表格中某个数量单元格其有效性是 ...
- wait和waitpid函数
来源:http://hohahohayo.blog.163.com/blog/static/120816010200971210230362/ wait(等待子进程中断或结束)表头文件 #in ...
- Python基础之 一 补充
三元运算: 语法:result = 值1 if 条件 else 值2 当条件为真时,result = 值1 当条件为假时,result = 值2 进制: 二进制:01 八进制:01234567 十进制 ...
- Devu and Flowers lucas定理+容斥原理
Devu wants to decorate his garden with flowers. He has purchased n boxes, where the i-th box contain ...
- java List.add操作可以指定位置
java List.add操作可以指定位置,addAll也可以指定: 使用: public class Test02 { public static void main(String[] args) ...