[luogu P1312]Mayan游戏
其实就是一道锻炼码力的简单题……
看到题目中的\(0<x\leqslant 5\)也就知道是爆搜了吧(
我们仿照写游戏的方法多写几个函数,能够有效降低错误率(确信
我们写出大致的搜索流程来:
如果当前步数大于\(n\)直接返回;
如果当前已经为终态,直接输出答案;
否则枚举每种可能情况继续搜。
没错就是这么暴力
接下来讲具体实现。
首先我们对全局变量和数组进行一下约定:
int n;//见题目
int board[10][10];//棋盘
int step[10][10];//存储步数
int mem[10][10][10];//鉴于搜索下一步的时候我们会不可避免地更改原数组,我们需要保存一下当前的状态
bool del[10][10];//见remove函数部分
一开始的读入非常简单:读到0换行即可
scanf("%d",&n);
for(int i=1;i<=5;i++)
{
int cnt=0;
while(1)
{
int xx;scanf("%d",&xx);
if(xx==0)break;
board[i][++cnt]=xx;
}
}
我们需要对题目的一些操作进行一下模拟。
首先是fall函数:它让悬空的块下落。
可以发现,我们用一个变量来存下移的最终位置,就可以简单地进行实现。
void fall()
{
int cnt;
for(int i=1;i<=5;i++)
{
cnt=0;
for(int j=1;j<=7;j++)
{
if(board[i][j]==0)cnt++;
else
{
if(cnt==0)continue;
board[i][j-cnt]=board[i][j];
board[i][j]=0;
}
}
}
}
然后是三消remove函数:
我们分别暴力判断横向和纵向每一次可以消掉哪些块,全都用del数组给标记出来,最后一起消掉。
别忘了最后要将del数组清零,消完之后fall一次让可能悬空的块下坠。
当然就像样例一样,一次消除是:消除当前->下坠->出现新的可三消块->再次消除当前……
于是我们将这个函数修改一下,让它发现本次有消除操作就返回1,没有就返回0。
于是我们可以这样调用remove函数:
while(remove());
简单粗暴(
remove函数实现:
bool remove()
{
bool flag=0;
for(int i=1;i<=5;i++)
for(int j=2;j<=6;j++)
if(board[i][j]!=0&&board[i][j]==board[i][j-1]&&board[i][j]==board[i][j+1])
{
flag=1;
del[i][j]=del[i][j-1]=del[i][j+1]=1;
}
for(int i=2;i<=4;i++)
for(int j=1;j<=7;j++)
if(board[i][j]!=0&&board[i][j]==board[i-1][j]&&board[i][j]==board[i+1][j])
{
flag=1;
del[i][j]=del[i-1][j]=del[i+1][j]=1;
}
if(!flag)return 0;
for(int i=1;i<=5;i++)
for(int j=1;j<=7;j++)
if(del[i][j])
board[i][j]=del[i][j]=0;
fall();
return 1;
}
接下来是移动块函数move和判断是否结束函数gameover。
move函数只需要移动一次并调用fall坠落一次,然后remove即可。
gameover直接全屏扫。
void move(int xx,int yy,int dir)//用dir标记方向
{
swap(board[xx][yy],board[xx+dir][yy]);
fall();while(remove());
}
bool gameover()
{
for(int i=1;i<=5;i++)
if(board[i][1]!=0)
return 0;
return 1;
}
接下来是dfs函数的枚举部分。
首先我们用mem储存一下;
然后只需要分方向枚举,枚举到一种情况就记录步数继续搜;
回溯的时候撤销所记录的步数,用mem数组换回原来的状态即可。
一个小剪枝:在交换之前判断一下,避免将相同的块交换即可。
for(int i=1;i<=5;i++)
for(int j=1;j<=7;j++)
mem[xx][i][j]=board[i][j];
for(int i=1;i<=5;i++)
for(int j=1;j<=7;j++)
if(board[i][j]!=0)
{
if(i<=4&&board[i][j]!=board[i+1][j])
{
move(i,j,1);
step[xx][1]=i-1;step[xx][2]=j-1;step[xx][3]=1;
dfs(xx+1);
step[xx][1]=step[xx][2]=step[xx][3]=-1;
for(int i=1;i<=5;i++)
for(int j=1;j<=7;j++)
board[i][j]=mem[xx][i][j];
}
if(i>=2&&board[i][j]!=board[i-1][j])
{
move(i,j,-1);
step[xx][1]=i-1;step[xx][2]=j-1;step[xx][3]=-1;
dfs(xx+1);
step[xx][1]=step[xx][2]=step[xx][3]=-1;
for(int i=1;i<=5;i++)
for(int j=1;j<=7;j++)
board[i][j]=mem[xx][i][j];
}
}
于是我们就这么水完了一道蓝题
完整代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
int n,board[10][10],step[10][10],mem[10][10][10];
bool del[10][10];
void fall()
{
int cnt;
for(int i=1;i<=5;i++)
{
cnt=0;
for(int j=1;j<=7;j++)
{
if(board[i][j]==0)cnt++;
else
{
if(cnt==0)continue;
board[i][j-cnt]=board[i][j];
board[i][j]=0;
}
}
}
}
bool remove()
{
bool flag=0;
for(int i=1;i<=5;i++)
for(int j=2;j<=6;j++)
if(board[i][j]!=0&&board[i][j]==board[i][j-1]&&board[i][j]==board[i][j+1])
{
flag=1;
del[i][j]=del[i][j-1]=del[i][j+1]=1;
}
for(int i=2;i<=4;i++)
for(int j=1;j<=7;j++)
if(board[i][j]!=0&&board[i][j]==board[i-1][j]&&board[i][j]==board[i+1][j])
{
flag=1;
del[i][j]=del[i-1][j]=del[i+1][j]=1;
}
if(!flag)return 0;
for(int i=1;i<=5;i++)
for(int j=1;j<=7;j++)
if(del[i][j])
board[i][j]=del[i][j]=0;
fall();
return 1;
}
void move(int xx,int yy,int dir)
{
swap(board[xx][yy],board[xx+dir][yy]);
fall();while(remove());
}
bool gameover()
{
for(int i=1;i<=5;i++)
if(board[i][1]!=0)
return 0;
return 1;
}
void dfs(int xx)
{
if(gameover())
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=3;j++)printf("%d ",step[i][j]);
printf("\n");
}
exit(0);
}
if(xx>n)return;
for(int i=1;i<=5;i++)
for(int j=1;j<=7;j++)
mem[xx][i][j]=board[i][j];
for(int i=1;i<=5;i++)
for(int j=1;j<=7;j++)
if(board[i][j]!=0)
{
if(i<=4&&board[i][j]!=board[i+1][j])
{
move(i,j,1);
step[xx][1]=i-1;step[xx][2]=j-1;step[xx][3]=1;
dfs(xx+1);
step[xx][1]=step[xx][2]=step[xx][3]=-1;
for(int i=1;i<=5;i++)
for(int j=1;j<=7;j++)
board[i][j]=mem[xx][i][j];
}
if(i>=2&&board[i][j]!=board[i-1][j])
{
move(i,j,-1);
step[xx][1]=i-1;step[xx][2]=j-1;step[xx][3]=-1;
dfs(xx+1);
step[xx][1]=step[xx][2]=step[xx][3]=-1;
for(int i=1;i<=5;i++)
for(int j=1;j<=7;j++)
board[i][j]=mem[xx][i][j];
}
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=5;i++)
{
int cnt=0;
while(1)
{
int xx;scanf("%d",&xx);
if(xx==0)break;
board[i][++cnt]=xx;
}
}
dfs(1);
printf("-1\n");
return 0;
}
最慢的点跑了1.09s,但还是够AC了(笑
[luogu P1312]Mayan游戏的更多相关文章
- Luogu P1312 Mayan游戏(搜索)
P1312 Mayan游戏 题意 题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个\(7\)行\(\times 5\)列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必 ...
- [题目] Luogu P1312 Mayan游戏
题面 题目描述 $ Mayan puzzle $是最近流行起来的一个游戏.游戏界面是一个 \(7行 \times 5列\)的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放 ...
- 洛谷P1312 Mayan游戏
P1312 Mayan游戏 题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他 ...
- [NOIP2011] 提高组 洛谷P1312 Mayan游戏
题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.游戏通关是指在规定 ...
- P1312 Mayan游戏
题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.游戏通关是指在规定 ...
- 洛谷 P1312 Mayan游戏
题解:搜索+模拟 剪枝: 最优性剪枝:x从小到大,y从小到大,第一次搜到的就是字典序最小 的最优解. 最优性剪枝:把一个格子和左边格子交换,和左边格子和右边格 子交换是等价的,显然让左边格子和右边交换 ...
- 洛古 P1312 Mayan游戏(dfs+剪枝)
题目链接 这道题和俄罗斯方块很像 很明显,我们可以看出这是一个dfs,但是,我们需要几条剪枝: 1.如果只剩下1个或2个同样颜色的方块,那么直接退出 2.相同的块不用交换 3.注意优先性,优先左边换右 ...
- [Luogu 1312] noip11 Mayan游戏
[Luogu 1312] noip11 Mayan游戏 Problem: Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即 ...
- 洛谷P1312 [NOIP2011提高组Day1T3]Mayan游戏
Mayan游戏 题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.游 ...
随机推荐
- 【LeetCode】989. Add to Array-Form of Integer 解题报告(C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 数组转整数再转数组 模拟加法 日期 题目地址:htt ...
- 【LeetCode】438. Find All Anagrams in a String 解题报告(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 滑动窗口 双指针 日期 题目地址:https://l ...
- 【LeetCode】113. Path Sum II 路径总和 II 解题报告(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.me/ 文章目录 题目描述 题目大意 解题方法 BFS DFS 日期 题目地址:https:// ...
- 1067 - Combinations
1067 - Combinations PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 32 MB Giv ...
- 【漏洞复现】ThinkAdmin v5和v6 未授权列目录任意文件读取(CVE-2020-25540)
ThinkAdmin v5和v6 未授权列目录/任意文件读取(CVE-2020-25540) 漏洞简介 ThinkAdmin是一套基于ThinkPHP框架的通用后台管理系统.ThinkAdmin v6 ...
- Nginx应用场景配置
Nginx应用全入门 基础回顾 Nginx是什么? Nginx是一个高性能的HTTP和反向代理web服务器,特点是内存少,并发能力强 Nginx能做什么 Http服务器(Web服务器) 反向代理服务器 ...
- .NET 云原生架构师训练营(ASP .NET Core 整体概念推演)--学习笔记
演化与完善整体概念 ASP .NET Core 整体概念推演 整体概念推演到具体的形式 ASP .NET Core 整体概念推演 ASP .NET Core 其实就是通过 web framework ...
- 编写Java程序,编写自定义异常类封装将棋子落在格子中已有棋子的异常
返回本章节 返回作业目录 需求说明: 完善控制台版五子棋,判断用户所下棋子的位置,是否已经存在棋子,如果已经存在,则抛出用户自定义异常,提示用户该位置已经有棋子. 实现思路: 创建用户自定义异常类Go ...
- 为什么说DI解耦
为什么说IOC/DI(控制反转/依赖注入)降低耦合 public class HomeController : Controller { private readonly IStudentRepons ...
- C# 高性能对象复制
需求背景:对象复制性能优化:同时,在对象复制时,应跳过引用类型的null值复制,值类型支持值类型向可空类型的复制 -------------- 1 using Common; 2 using Syst ...