写了一下午,终于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游戏 搜索 + 模拟 + 剪枝的更多相关文章

  1. 洛谷 P1312 [ NOIP 2011 ] Mayan游戏 —— 搜索+模拟

    题目:https://www.luogu.org/problemnew/show/P1312 还是不擅长这种题,所以参考了一下TJ: 其实也很好搜,按字典序,先搜右移,再搜左移: 不交换相同颜色的两个 ...

  2. Luogu P1312 Mayan游戏(搜索)

    P1312 Mayan游戏 题意 题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个\(7\)行\(\times 5\)列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必 ...

  3. NOIP2011 Mayan游戏

    3 Mayan游戏 题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上 ...

  4. [NOIP2011] mayan游戏(搜索+剪枝)

    题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.游戏通关是指在规定 ...

  5. [noip2011 luogu1312] Mayan游戏(模拟)

    原题:传送门 大模拟- 两个剪枝: 1.如果左边不为空就不往左边走(因为一定不如左边的移到右边优) 2.如果相邻两颜色相同不需移动 当然也有别的小剪枝(我没写)比如如果当前某一颜色剩余块数满足1< ...

  6. NOIP Mayan游戏 - 搜索

    Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个7行5列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.游戏通关是指在规定的步数内消除所有 ...

  7. [NOIP2011]Mayan游戏 题解

    题目大意: 有一个5*7的方格,上面有几种颜色的方块,如果在一横行或者竖列上有连续三个或者三个以上相同颜色的方块,则它们将立即被消除,方块消除之后,消除位置之上的方块将掉落.每步移动可以且仅可以沿横向 ...

  8. NOIp 2011 mayan游戏 搜索

    题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.游戏通关是指在规定 ...

  9. noip2011 玛雅游戏 大模拟

    深搜+模拟 需要剪枝:同一移动向右移了就不需要向左移了 #include<cstdio> #include<cstring> #include<iostream> ...

随机推荐

  1. Python中对两种utf-8格式的理解

    1.python文件开头utf-8格式的理解 2.程序中读取文件时utf-8格式的理解 aa.py文件代码示例: #!/usr/bin/python # -*- coding:utf-8 -*- fr ...

  2. 只读事务(@Transactional(readOnly = true))的一些概念

    念:从这一点设置的时间点开始(时间点a)到这个事务结束的过程中,其他事务所提交的数据,该事务将看不见!(查询中不会出现别人在时间点a之后提交的数据) 应用场合: 如果你一次执行单条查询语句,则没有必要 ...

  3. 【ACM】hdu_zs1_1001_水仙花数_201307271504

    水仙花数 Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other)Total Submissio ...

  4. [jQuery]jQuery获取URL参数

    // jQuery url get parameters function [获取URL的GET参数值]// <code>// var GET = $.urlGet(); //获取URL的 ...

  5. ABCDE

    ABCDE A-Artificial intelligence 人工智能 B-Block chain 区块链 C-Cloud 云 D-Big Data 大数据 E-Ecology 互联网生态是以互联网 ...

  6. 利用Ajax调用controller方法并传递参数

    一.背景由于近期工作需要将人脸识别功能与选课系统结合,但是对前端知识了解的很少,只能边做边学了,因此在这边把遇到的一些坑说明一下,希望能帮助到像我一样的初学者 二.具体内容这里采用框架为MVC,如果想 ...

  7. 黑马day01xml 解析方式与原理分析

    dom解析方式和sax解析

  8. 【cl】子查询应用场景

    有推荐人/没有推荐人的 recommender_id is null / is not null 谁是推荐人=他的id是别人的recommender_id=某个人的recommender_id是他的i ...

  9. Cocos2d-x3.3beta0创建动画的3种方式

    1.单独载入精灵对象 渲染效率低,浪费资源,不推荐用该方法.代码例如以下:注:代码仅仅需贴到HelloWorldScene.cpp中就可以. //First,单独渲染每个精灵帧 auto sprite ...

  10. c16---字符串

    // // main.c // 字符串的基本概念,字符串和字符数组的共用的char[], #include <stdio.h> int main(int argc, const char ...