Noip2011 Mayan游戏 搜索 + 模拟 + 剪枝
写了一下午,终于AC了。
由于n<=5, 所以不需要太多的剪枝和技巧也能过。可以将操作后的消方块和下落和剪枝函数写到一个结构体中,这样会减少调试难度,更加简洁。
可以采用如下剪枝:
1. 如果当前有一种颜色少于两个,则一定无解。
2. 如果相邻颜色相同则不交换。
3. 优先考虑右移
4. 其实可以开一个unordered_map来避免重复搜索,由于笔者已经筋疲力尽,就没有进行这部优化(但其实n的规模太小,不开也无所谓)。
代码:
#include<cstdio>
#include<vector>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<deque>
using namespace std;;
const int n = 7;
const int m = 5;
int board[10][10], spare[10][10], target;
struct Ans
{
int x,y,g;
Ans(int x = 0, int y = 0,int g = 0):x(x),y(y),g(g){}
};
deque<Ans>Q;
struct Operation
{
inline int get_num()
{
int cnt = 0;
for(int i = 1;i <= n; ++i)
for(int j = 1;j <= m; ++j)
if(spare[i][j])++cnt;
return cnt;
}
inline int cut()
{
int col[16];
memset(col,0,sizeof(col));
for(int i = 1;i <= n;++i)
for(int j = 1;j <= m;++j) ++ col[spare[i][j]];
for(int i = 1;i <= 15;++i)
if(col[i] && col[i] <= 2)return 1;
return 0;
}
inline int clear_block()
{
int flag = 0;
int mark[10][10];
memset(mark,0,sizeof(mark));
for(int i = 1;i <= n;++i)
{
for(int j = 1;j <= m;++j)
{
if(!spare[i][j])continue;
if(i + 2 <= n)
{
int cur = i;
while(spare[cur + 1][j] == spare[cur][j]) ++cur;
if(cur - i + 1 >= 3)
{
flag = 1;
int y = i;
while(spare[y][j] == spare[i][j]) mark[y][j] = 1, y += 1;
}
}
if(j + 2 <= m)
{
int cur = j;
while(spare[i][cur + 1] == spare[i][cur])++cur;
if(cur - j + 1 >= 3)
{
flag = 1;
int y = j;
while(spare[i][y] == spare[i][j]) mark[i][y] = 1, y += 1;
}
}
}
}
for(int i = 1;i <= n; ++i)
for(int j = 1;j <= m; ++j)
if(mark[i][j])spare[i][j] = 0;
return flag;
}
inline void down()
{
for(int col = 1; col <= m; ++col)
{
int bottom = n, cur = n;
while(bottom >= 1 && cur >= 1)
{
while(spare[bottom][col] && bottom >= 1) --bottom;
cur = bottom;
while(cur >= 1 && !spare[cur][col]) --cur;
if(cur >= 1)
{
int i = bottom ,j = cur;
while(spare[j][col] && j >= 1 && i >= 1)
{
spare[i][col] = spare[j][col];
spare[j][col] = 0;
--i;
--j;
}
}
}
}
}
inline void update()
{
down();
while(clear_block()) down();
}
}T;
void dfs(int nums,int arr[10][10])
{
for(int i = 1;i <= n;++i)
for(int j = 1;j <= m;++j)spare[i][j] = arr[i][j];
T.update();
for(int i = 1;i <= n;++i)
for(int j = 1;j <= m;++j)arr[i][j] = spare[i][j];
if(nums == target)
{
if(!T.get_num())
{
while(!Q.empty())
{
Ans p = Q.front();
printf("%d %d %d\n",p.x-1, 7-p.y, p.g);
Q.pop_front();
}
exit(0);
}
return;
}
if(!T.get_num() || T.cut())return;
int h[10][10];
memset(h,0,sizeof(h));
for(int i = 1;i <= n;++i)
for(int j = 1;j <= m;++j)h[i][j] = arr[i][j];
for(int j = 1;j <= m;++j)
for(int i = 7; i >= 1;--i)
{
if(!h[i][j])continue;
if(j < m && arr[i][j] != arr[i][j+1])
{
swap(h[i][j],h[i][j+1]);
Q.push_back(Ans(j,i,1));
dfs(nums+1,h);
Q.pop_back();
for(int i = 1;i <= n;++i)
for(int j = 1;j <= m;++j)h[i][j] = arr[i][j];
}
if(j > 1 && !arr[i][j-1])
{
swap(h[i][j],h[i][j-1]);
Q.push_back(Ans(j,i,-1));
dfs(nums+1,h);
Q.pop_back();
swap(h[i][j],h[i][j-1]);
for(int i = 1;i <= n;++i)
for(int j = 1;j <= m;++j)h[i][j] = arr[i][j];
}
}
}
int main()
{
//freopen("in.txt","r",stdin);
scanf("%d",&target);
for(int i = 1;i <= 5; ++i)
{
for(int j = 7; ;--j)
{
int a;
scanf("%d",&a);
if(!a)break;
board[j][i] = a;
}
}
dfs(0,board);
printf("-1");
return 0;
}
Noip2011 Mayan游戏 搜索 + 模拟 + 剪枝的更多相关文章
- 洛谷 P1312 [ NOIP 2011 ] Mayan游戏 —— 搜索+模拟
题目:https://www.luogu.org/problemnew/show/P1312 还是不擅长这种题,所以参考了一下TJ: 其实也很好搜,按字典序,先搜右移,再搜左移: 不交换相同颜色的两个 ...
- Luogu P1312 Mayan游戏(搜索)
P1312 Mayan游戏 题意 题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个\(7\)行\(\times 5\)列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必 ...
- NOIP2011 Mayan游戏
3 Mayan游戏 题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上 ...
- [NOIP2011] mayan游戏(搜索+剪枝)
题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.游戏通关是指在规定 ...
- [noip2011 luogu1312] Mayan游戏(模拟)
原题:传送门 大模拟- 两个剪枝: 1.如果左边不为空就不往左边走(因为一定不如左边的移到右边优) 2.如果相邻两颜色相同不需移动 当然也有别的小剪枝(我没写)比如如果当前某一颜色剩余块数满足1< ...
- NOIP Mayan游戏 - 搜索
Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个7行5列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.游戏通关是指在规定的步数内消除所有 ...
- [NOIP2011]Mayan游戏 题解
题目大意: 有一个5*7的方格,上面有几种颜色的方块,如果在一横行或者竖列上有连续三个或者三个以上相同颜色的方块,则它们将立即被消除,方块消除之后,消除位置之上的方块将掉落.每步移动可以且仅可以沿横向 ...
- NOIp 2011 mayan游戏 搜索
题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.游戏通关是指在规定 ...
- noip2011 玛雅游戏 大模拟
深搜+模拟 需要剪枝:同一移动向右移了就不需要向左移了 #include<cstdio> #include<cstring> #include<iostream> ...
随机推荐
- What identity values you get with the @@IDENTITY and SCOPE_IDENTITY functions
--测试表及数据 CREATE TABLE TZ ( Z_id int IDENTITY(1,1)PRIMARY KEY, Z_name varchar(20) NOT NULL) INSE ...
- eclipse实现批量修改文件的编码方式
http://blog.csdn.net/haorengoodman/article/details/38493007 在eclipse+MyEclipse环境下,打开一个jsp文件,经常发现汉字无法 ...
- 消息队列Rabbit安装
先安装elang 再安装Rabbit *Rabbit安装路径不能有空格 安装完成
- 洛谷—— P2647 最大收益
https://www.luogu.org/problem/show?pid=2647 题目描述 现在你面前有n个物品,编号分别为1,2,3,……,n.你可以在这当中任意选择任意多个物品.其中第i个物 ...
- 洛谷 P2728 纺车的轮子 Spinning Wheels
P2728 纺车的轮子 Spinning Wheels 题目背景 一架纺车有五个纺轮(也就是五个同心圆),这五个不透明的轮子边缘上都有一些缺口.这些缺口必须被迅速而准确地排列好.每个轮子都有一个起始标 ...
- 一次SQLSERVER触发器编写感悟
背景:BOSS须要我写一个工厂採集端到server端的数据同步触发器,数据库採用的是sqlserver2008 需求:将多台採集机的数据同步到server中,假设採集端数据库与server数据库连接失 ...
- Webx框架:Spring Schema 和 Spring Ext
webx诞生的原因是当时市面上没有好用的web框架.如今的Web框架有非常多.然后它们背后的思想都是相似的,并且越来越趋同. Spring Schema 在传统的spring中,配置bean时须要手动 ...
- 【BZOJ】2140 稳定婚姻
[解析]Hash,离散化.Tarjan [分析] 对于每一个名字.首先离散化成编号. 用hash或者其它,反正不要最主要的即可了.否则O(N^2L)会爆掉. 然后请參考:http://www.cnbl ...
- 几个比較好的IT站和开发库官网
几个比較好的IT站和开发库官网 1.IT技术.项目类站点 (1)首推CodeProject,一个国外的IT站点,官网地址为:http://www.codeproject.com,这个站点为程序开发人员 ...
- 【LeetCode OJ 268】Missing Number
题目链接:https://leetcode.com/problems/missing-number/ 题目:Given an array containing n distinct numbers t ...