洛古 P1312 Mayan游戏(dfs+剪枝)
这道题和俄罗斯方块很像
很明显,我们可以看出这是一个dfs,但是,我们需要几条剪枝:
1.如果只剩下1个或2个同样颜色的方块,那么直接退出
2.相同的块不用交换
3.注意优先性,优先左边换右边
但是这题就这么样就完了吗
显然,并没有这么简单:剪枝清楚了,你确定就能写出来吗(这是我写过最长的dfs)
接下来讲一下我的程序架构:
init函数:输入,存储数据
fall函数:模拟方块下落
printans函数:输出答案
clear函数:清除棋盘
isempty函数:判断是否为空
judge函数:剪枝1
dfs函数:搜索
下面是代码,看不懂上面的话,代码里也有注释
#include <bits/stdc++.h>
using namespace std; const int N = ;
const int M = ; int maxstep, chess[N][M];
int cnt[];
int answer[][]; void init()
{
cin>>maxstep;
for(int i=; i<N; i++)
{
int j=,x;
cin>>x;
while(x!=)
{
chess[i][j]=x;
j++;
cin>>x;
}
}
} void fall() //清除后方块下落
{
for(int i=; i<N; i++)
for(int j=; j<M; j++)
{
if(chess[i][j]!=)
continue;
int k;
for(k=j+; k<M; k++)
if(chess[i][k]!=)
{
swap(chess[i][j],chess[i][k]);
break;
}
if(k==M)
break;
}
} void printans() //输出
{
for(int i=; i<maxstep; i++)
printf("%d %d %d\n",answer[i][],answer[i][],answer[i][]);
return;
} bool clear() //清除棋盘
{
bool empty[N][M];
memset(empty,false,sizeof(empty));
for(int i=; i<N-; i++)
for(int j=; j<M; j++)
if(chess[i][j]!= && chess[i][j]==chess[i+][j]
&& chess[i+][j]==chess[i+][j]) {
empty[i][j]=empty[i+][j]=empty[i+][j]=true;
} for(int i=; i<N; i++)
for(int j=; j<M-; j++)
if(chess[i][j]!= && chess[i][j]==chess[i][j+]
&& chess[i][j+]==chess[i][j+]) {
empty[i][j]=empty[i][j+]=empty[i][j+]=true;
} bool res=false;
for(int i=; i<N; i++)
for(int j=; j<M; j++)
if(empty[i][j])
{
chess[i][j]=;
res=true;
}
return res;
} bool isempty() // 判断棋盘是否为空
{
for(int i=; i<N; i++)
for(int j=; j<M; j++)
if(chess[i][j]!=)
return false;
return true;
} bool judge() //判断是否有一种颜色的块数量为1或2
{
memset(cnt,,sizeof(cnt));
for(int i=; i<N; i++)
for(int j=; j<M; j++)
cnt[chess[i][j]]++;
for(int i=; i<=; i++)
if(cnt[i]==||cnt[i]==)
return false;
return true;
} bool dfs(int step) //搜索
{
if(isempty()) //发现一组解
{
printans();
return true;
}
if(step>=maxstep || !judge()) //剪枝与结束条件
return false; int now[N][M]; // 记录当前状态,回溯时候用
for(int i=; i<N; i++) //复制棋盘
for(int j=; j<M; j++)
now[i][j]=chess[i][j]; for(int i=; i<N; i++)
for(int j=; j<M; j++) //枚举每一个方块
{
//右移
if(i!=N- && chess[i][j]!= && chess[i][j]!=chess[i+][j])
{
swap(chess[i][j], chess[i+][j]);
answer[step][]=i;
answer[step][]=j;
answer[step][]=;
fall();
while(clear())
fall();
if(dfs(step+))
return true;
} for(int k1=; k1<N; k1++)
for(int k2=; k2<M; k2++)
chess[k1][k2]=now[k1][k2]; //左移
if(i!= && chess[i][j]!= && chess[i-][j]==)
{
swap(chess[i][j], chess[i-][j]);
answer[step][]=i;
answer[step][]=j;
answer[step][]=-;
fall();
while(clear())
fall();
if(dfs(step+))
return true;
} for(int k1=; k1<N; k1++)
for(int k2=; k2<M; k2++)
chess[k1][k2]=now[k1][k2];
}
return false;
} /*
搜索+剪枝
剪枝原则:
1,交换两个相同颜色的块没有意义。
2,如果一种颜色的块数量为1或2,则当前局面无解。
3,因为要求字典序最小的解,所以一个块仅当左边为空时尝试左移
(若左面有方块,那么在搜i-1列时将其右移,和在i列时左移是等效的,故可以剪枝)
*/
int main()
{
ios::sync_with_stdio(false);
cin.tie(); init();
if(!dfs())
cout<<-<<endl;
return ;
}
补充:说到俄罗斯方块,我又想起来USACO的这道题,有兴趣的同学可以去做做
洛古 P1312 Mayan游戏(dfs+剪枝)的更多相关文章
- 洛谷P1312 Mayan游戏
P1312 Mayan游戏 题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他 ...
- [NOIP2011] 提高组 洛谷P1312 Mayan游戏
题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.游戏通关是指在规定 ...
- 洛谷 P1312 Mayan游戏
题解:搜索+模拟 剪枝: 最优性剪枝:x从小到大,y从小到大,第一次搜到的就是字典序最小 的最优解. 最优性剪枝:把一个格子和左边格子交换,和左边格子和右边格 子交换是等价的,显然让左边格子和右边交换 ...
- Luogu P1312 Mayan游戏(搜索)
P1312 Mayan游戏 题意 题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个\(7\)行\(\times 5\)列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必 ...
- [题目] Luogu P1312 Mayan游戏
题面 题目描述 $ Mayan puzzle $是最近流行起来的一个游戏.游戏界面是一个 \(7行 \times 5列\)的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放 ...
- 洛谷 1312 Mayan游戏——暴搜+剪枝
题目:https://www.luogu.org/problemnew/show/P1312 自己写了很久.又T又WA的. 发现对题理解有误.改完后应该只有T了,但还是T的. 自己写了许多剪枝,很鸡肋 ...
- P1312 Mayan游戏
题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.游戏通关是指在规定 ...
- [luogu P1312]Mayan游戏
其实就是一道锻炼码力的简单题-- 看到题目中的\(0<x\leqslant 5\)也就知道是爆搜了吧( 我们仿照写游戏的方法多写几个函数,能够有效降低错误率(确信 我们写出大致的搜索流程来: 如 ...
- [洛谷P1731][NOI1999]生日蛋糕(dfs)(剪枝)
典型的深搜+剪枝策略 我们采用可行性剪枝.上下界剪枝.优化搜索顺序剪枝.最优性剪枝的方面来帮助我们进行剪枝. 也许有人还不知道剪枝,那我就弱弱地为大家补习一下吧qwq: .优化搜索顺序: 在一些搜索问 ...
随机推荐
- linux公社大量免费的在线android资料
2011年linux数据库的android在线分享 linux公社:开源公社 本文撰写:杨凯专属频道 下载如需密码,详见博客案例:点击我去查看密码 2011年9月12日 21: ...
- jQuery2.0.0版本以后不再支持ie8的原因
在引用jQuery时,引用高版本的Jq会在IE8下报错,在网上查了一下,jq在2.0+的版本就已经放弃对ie8的支持了.之前没有仔细研究过jq版本,借此机会去看了一下jq版本的知识.一.如何查看jq的 ...
- 实现子数组和绝对值差最小 - Objective-C
类似于背包问题,前提条件是数组全是正整数和0,先求和Sum,再从子数组中找出接近Sum/2的子数组 @interface TempState : NSObject @property (nonatom ...
- 论文笔记[Slalom: Fast, Verifiable and Private Execution of Neural Networks in Trusted Hardware]
作者:Florian Tramèr, Dan Boneh [Standford University] [ICLR 2019] Abstract 为保护机器学习中隐私性和数据完整性,通常可以利用可信 ...
- Job for network.service failed because the control process exited with error code问题
Job for network.service failed because the control process exited with error code问题 因为是克隆的,所以需要重新修改静 ...
- STL迭代器的使用、正向、逆向输出双向链表中的所有元素
*/ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...
- React之mockjs+sass+生命周期函数
mdn W3C标准网站 运行sass cnpm i -D node-sass-chokidar npm-run-all rem单位设置 <script> //rem单位设置 documen ...
- go微服务框架kratos学习笔记十(熔断器)
目录 go微服务框架kratos学习笔记十(熔断器) 什么是熔断 熔断器逻辑 kratos Breaker kratos 熔断逻辑 kratos熔断器使用说明 bladmaster client br ...
- shell 获取字符创长度&&识别当前使用的shell&&检查是否为超级用户
1.获得字符串长度 可以使用下面的方法获得变量值得长度: length=${#value} 例如: [root@gameserver1 shell]# var=12345678 [root@games ...
- 7-44 jmu-python-区间数之和 (10 分)
输入一个区间,计算里面能被3整除或被5整除的数和. 输入格式: 每行输入一个数据,代表区间左界和右界.区间包含左界和右界.数据必须是整数. 输出格式: 满足条件数和. 输入样例: 2 10 输出样例: ...