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 因为只会询问一个点被谁覆盖, 而且后面 ...
随机推荐
- windows10开启内置ubuntu系统,使用xshell连接
windows安装配置ubuntu系统内置子系统 官方文档:https://docs.microsoft.com/zh-cn/windows/wsl/about https://www.jianshu ...
- 九度oj 题目1074:对称平方数
题目1074:对称平方数 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:6422 解决:2912 题目描述: 打印所有不超过n(n<256)的,其平方具有对称性质的数. 如11*11 ...
- 全文搜索(A-5)-推荐算法
基于内容的推荐算法: 协同过滤推荐算法: 混合推荐算法: 基于内容的推荐算法做了如下假设:用户会喜欢和原来喜欢的物品相类似的项目.
- 【IntelliJ】IDEA使用--字体、编码和基本设置
IDEA这么高端的工具之前只是断断续续使用了一下,因为项目的开发都是在eclipse上,每次学习IDEA的使用都得上网搜索半天,今天自己整理一下,方便以后查阅. IDEA版本15.0.4 字体 界面字 ...
- Linux下汇编语言学习笔记63 ---
这是17年暑假学习Linux汇编语言的笔记记录,参考书目为清华大学出版社 Jeff Duntemann著 梁晓辉译<汇编语言基于Linux环境>的书,喜欢看原版书的同学可以看<Ass ...
- 执行循环任务new Timer().schedule(new TimerTask(){},0,1000);
package com.pingyijinren.test; import android.support.v7.app.AppCompatActivity; import android.os.Bu ...
- 调用系统文件管理器选择图片,调用系统裁剪AIP对图片处理,显示裁剪之后的图片
package com.pingyijinren.test; import android.annotation.TargetApi; import android.app.Notification; ...
- 2017-10-03-afternoon
P100 zhx 竞赛时间:????年??月??日??:??-??:?? 题目名称 a b c 名称 a b c 输入 a.in b.in c.in 输出 a.out b.out c.out 每个测试 ...
- 何为幻读?MySQL又是如何解决幻读的?
一.什么是幻读 在一次事务里面,多次查询之后,查询的结果集的个数不一致的情况叫做幻读.而多出来或者少的哪一行被叫做 幻行 二.为什么要解决幻读 在高并发数据库系统中,需要保证事务与事务之间的隔离性,还 ...
- windows 7 文件加密设置
方法/步骤1 加密文件 1 右击需加密的文件,选择“属性”命令. 2 在属性对话框的“常规‘选项卡中单击”高级“按钮. 3 在弹出的对话框中选中”加密内容以便保护数据“复选框,单击”确定“按钮. 4 ...