洛古 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: .优化搜索顺序: 在一些搜索问 ...
随机推荐
- 吴裕雄--天生自然python学习笔记:Python3 迭代器与生成器
迭代器 迭代是Python最强大的功能之一,是访问集合元素的一种方式. 迭代器是一个可以记住遍历的位置的对象. 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退 ...
- C# 输出&输入&类型强制转换
输入字符串 String s; s=Console.ReadLine(); 输出字符串 Console.WritrLine(s); 输出分两种 ①占位符输出:Console.WriteLine(&qu ...
- 添砖加瓦:几种常见的数据摘要算法(MD5、CRC32、SHA1和SHA256)
1.算法概述 数据摘要算法是密码学算法中非常重要的一个分支,它通过对所有数据提取指纹信息以实现数据签名.数据完整性校验等功能,由于其不可逆性,有时候会被用做敏感信息的加密.数据摘要算法也被称为哈希(H ...
- 用Express 4和 MongoDB打造Todo List
本篇文章主要參考自DreamersLab - 用Express和MongoDB寫一個todo list.原文的教學內容是使用Express 3.x版,在這邊做簡單Express 4.12.1的todo ...
- appium使用相对坐标定位元素
最近在用appium做自动化时发现,有一些元素无法通过uiautomatorviewer进行定位,这样就只能通过相对坐标来进行定位了.但是,问题又来了:如何获取元素的坐标呢? 在网上找了半天也没找到相 ...
- css之制作三角形
箭头向上三角形 #triangle-up { width: 0; height: 0; border-left: 50px solid transparent; border-right: 50px ...
- Hihocoder1456 Rikka with Lattice
众所周知,萌萌哒六花不擅长数学,所以勇太给了她一些数学问题做练习,其中有一道是这样的:勇太有一个$n times m$的点阵,他想要从这$n times m$个点中选出三个点 ${A,B,C}$,满足 ...
- iPhone7产业链不为人知的辛酸
苹果金秋新品发布会是科技界的"春晚",年复一年地重复,难免会让人产生审美疲劳,但每逢中国教师节前后,全球的科技人士和媒体还是会不约而同地走到一起,等待苹果团队为之奉献出好的产品和 ...
- 网络字体反爬之pyspider爬取起点中文小说
前几天跟同事聊到最近在看什么小说,想起之前看过一篇文章说的是网络十大水文,就想把起点上的小说信息爬一下,搞点可视化数据看看.这段时间正在看爬虫框架-pyspider,觉得这种网站用框架还是很方便的,所 ...
- CSS——NO.5(格式化排版)
*/ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...