题目链接: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. mui.openWindow的html5+和web传参的兼容

    mui.openWindow兼容web&plus环境下的页面传参 背景介绍 刚刚好要写个微信公众号和html5+兼容的项目 发现总是用localStorage传参不是事啊 太不优雅了 想了想还 ...

  2. 23Spring使用JdbcTemplate和JdbcDaoSupport

    首先需要添加c3p0包和jdbc包 数据库: CREATE DATABASE IF NOT EXISTS `spring` /*!40100 DEFAULT CHARACTER SET utf8 */ ...

  3. linux 负载各项查看命令

    free -h top -c 查看使用情况 sar -r/s/b 查看IO状态 iostat -x 1 10 查看服务器的状态 vmstat 查看内存使用率最后的前10个进程 ps -aux |sor ...

  4. 51中xdata,idata,data,pdata的区别

    51系列中data,idata,xdata,pdata的区别 data: 固定指前面0x00-0x7f的128个RAM,可以用acc直接读写的,速度最快,生成的代码也最小. idata: 固定指前面0 ...

  5. 【转】Java IO流 overview

    Java流操作有关的类或接口: Java流类图结构: 流的概念和作用 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象.即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输 ...

  6. 游走(bzoj 3143)

    Description 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点, ...

  7. Gym 100792 King's Rout 拓扑排序

    K. King's Rout time limit per test 4.0 s memory limit per test 512 MB input standard input output st ...

  8. Inversion 归并求逆元

    bobo has a sequence a 1,a 2,…,a n. He is allowed to swap twoadjacent numbers for no more than k time ...

  9. 【小记事】电脑命令行开WiFi

    1.设置WiFi名称和密码 在命令行输入: netsh wlan set hostednetwork mode=allow WiFi名称 key=密码 2.开启WiFi 在命令行输入: netsh w ...

  10. POJ——T 2976 Dropping tests

    http://poj.org/problem?id=2976 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 13861   ...