首先,我们考虑搜索顺序,我们从第一列的第一格搜起,搜完当前列的方格的方格后,然后搜下一列,对于一个方格,我们优先右移,再搜左移.这样可以保证搜出来的字典序最小(因为先搜到的合法答案的字典序一定是最小的)

由于时间复杂度大概是,超时了,所以我们考虑剪枝:

1.如果一种颜色的方块只有1个或者2两个,那么就回溯

2.如果一个方块的左边有方块,则不要执行左移操作,因为这样的字典序一定不如右边的方块左移

3.一个错误的剪枝:如果左右方块一致,那么就不移动.原因是:题目要求步数要为n,有可能每次我们只走合法的路线,步数不足n次.

代码如下:

#include <bits/stdc++.h>
// #define LOCAL
#define INF 0x3f3f3f3f3f3f3f3f
#define IOS ios::sync_with_stdio(false), cin.tie(0)
#define int long long
#define debug(a) cerr << #a << "=" << a << endl;
using namespace std;
int n;
int cnt[12], g[5][7];
int bcnt[5][12], bg[5][5][7];
struct rec_{int x, y, d;
}path[6];
bool st[5][7];void mv(int a, int b, int c){swap(g[a][b], g[c][b]);for (;;){bool is_change = false;//先使用双指针处理每一列悬空的方块for (int x = 0; x < 5; ++x){int z = 0;for (int y = 0; y < 7; ++y)if (g[x][y])g[x][z++] = g[x][y];while (z < 7)g[x][z++] = 0;}//这里使用了类似延迟删除的技巧,将所有符合删除条件的方块打上标记,后面再一起删除memset(st, 0, sizeof st);for (int x = 0; x < 5; ++x)for (int y = 0; y < 7; ++y){if (g[x][y] == 0)continue;int l = x, r = x;while (l - 1 >= 0 && g[l - 1][y] == g[x][y])--l;while (r + 1 < 5 && g[r + 1][y] == g[x][y])++r;if (r - l + 1 >= 3){st[x][y] = true;is_change = true;}else{l = r = y;while (l - 1 >= 0 && g[x][l - 1] == g[x][y])--l;while (r + 1 < 7 && g[x][r + 1] == g[x][y])++r;if (r - l + 1 >= 3){st[x][y] = true;is_change = true;}}}if (!is_change)break;for (int x = 0; x < 5; ++x)for (int y = 0; y < 7; ++y)if (st[x][y]){--cnt[0];--cnt[g[x][y]];g[x][y] = 0;}}
}bool dfs(int u){if (u == n)return !cnt[0];//剪枝1:如果某个颜色的方块只有一个或者两个,那么就直接回溯for (int i = 0; i <= 10; ++i)if (cnt[i] == 1 || cnt[i] == 2)return false;//进行备份memcpy(bg[u], g, sizeof g);memcpy(bcnt[u], cnt, sizeof cnt);for (int x = 0; x < 5; ++x)for (int y = 0; y < 7; ++y){if (g[x][y] == 0)continue;int nx = x + 1;//先右移if (x + 1 < 5){path[u] = {x, y, 1};mv(x, y, nx);if (dfs(u + 1))return true;memcpy(g, bg[u], sizeof bg[u]);memcpy(cnt, bcnt[u], sizeof bcnt[u]);}nx = x - 1;//再左移,注意剪枝2:如果左边有方块,则不左移,因为左边的方块右移一定会比右边的方块左移字典序小if (x - 1 >= 0 && g[nx][y] == 0){path[u] = {x, y, -1};mv(x, y, nx);if (dfs(u + 1))return true;memcpy(g, bg[u], sizeof bg[u]);memcpy(cnt, bcnt[u], sizeof bcnt[u]);}}return false;}signed main(){
#ifdef LOCALfreopen("input.in", "r", stdin);freopen("output.out", "w", stdout);
#endifIOS;cin >> n;for (int i = 0; i < 5; ++i){int x = 0, t;while (cin >> t, t){g[i][x++] = t;++cnt[t];++cnt[0];}}if (dfs(0))for (int i = 0; i < n; ++i)cout << path[i].x << " " << path[i].y << " " << path[i].d << "\n";elsecout << -1 << "\n";return 0;
}

这里再额外提一嘴,这道题的模拟也是有难度的,对要删除的方块打上标记,延迟删除.

AcWing 185. 玛雅游戏 (dfs + 剪枝 + 模拟)相关推荐

  1. AcWing 168 生日蛋糕【DFS 剪枝 ☆】

    题目描述: 7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为Nπ的M层生日蛋糕,每层都是一个圆柱体. 设从下往上数第i层蛋糕是半径为Ri, 高度为Hi的圆柱. 当i < M时,要求 ...

  2. IDA* AcWing 181. 回转游戏

    IDA* AcWing 181. 回转游戏 原题链接 AcWing 181. 回转游戏 算法标签 搜索 IDA* 思路 本题采用 IDA* 算法,即迭代加深的 A* 算法. 估价函数: 统计中间8个方 ...

  3. 【Acwing 219. 剪纸游戏】

    [Acwing 219. 剪纸游戏] 题意: 给定一张 N×M 的矩形网格纸,两名玩家轮流行动. 在每一次行动中,可以任选一张矩形网格纸,沿着某一行或某一列的格线,把它剪成两部分. 首先剪出 1×1 ...

  4. DFS剪枝优化 小猫爬山 数独

    DFS剪枝策略总结 优化搜索顺序 优先搜索分支数少(剩余选择少)的情况 排除等效冗余 若对顺序没有要求 可以将排列转化为组合 可行性剪枝 不合法的情况不进行搜索 最优化剪枝 若当前的"消耗& ...

  5. POJ2688状态压缩(可以+DFS剪枝)

    题意:       给你一个n*m的格子,然后给你一个起点,让你遍历所有的垃圾,就是终点不唯一,问你最小路径是多少? 思路:       水题,方法比较多,最省事的就是直接就一个BFS状态压缩暴搜就行 ...

  6. poj2362 DFS+剪枝

    题大致做法就是对所有小棒子长度求和sum,sum就是正方形的周长,sum/4就是边长side. 问题就转变为:这堆小棒子能否刚好组合成为4根长度均为side的大棒子 不难了解,小棒子的长度越长,其灵活 ...

  7. Acwing 1084. 数字游戏 II

    Acwing 1084. 数字游戏 II 题意: 指定一个整数闭区间 [a.b],问这个区间内有多少个取模数. 取模数:这种数字必须满足各位数字之和 mod N 为 0. 题解: 数位dp 这里不细讲 ...

  8. Acwing 1082. 数字游戏

    Acwing 1082. 数字游戏 题意: 现在大家决定玩一个游戏,指定一个整数闭区间 [a,b],问这个区间内有多少个不降数. 题解: 利用数位dp的套路来做 我们还是利用前缀和来做 我们先求1~n ...

  9. [Leetcode][第39题][JAVA][组合总和][回溯][dfs][剪枝]

    [问题描述][中等] [解答思路] 1. 回溯 import java.util.ArrayDeque; import java.util.ArrayList; import java.util.De ...

最新文章

  1. 微信小程序与H5相互跳转和传递数据
  2. 解决:fatal: Not a valid object name: ‘master‘问题
  3. ABAP delete的用法
  4. 通过正则表达式分句提取中文内容
  5. 动态规划-装配线调度
  6. PHP使用GD库封装验证码类
  7. Java扑克牌(多线程)
  8. C/C++知识分享:C++标准库之 string 类型,各种运算全部掌握
  9. Spring Boot : Spring Boot Slf4j 以及 log4j 以及门面日志
  10. ajax常见的status状态码
  11. vbox linux centos 6,VirtualBox搭建 CentOS7.6
  12. openstack手动部署简单记录
  13. java 微信小程序 在线学习系统app
  14. 程序员工作交接文档怎么写_IT交接事项.doc
  15. win7连接远程服务器特别慢,win7远程桌面连接速度慢的问题如何解决
  16. 还在浪费时间创建工程图?6分钟教你自定义SOLIDWORKS工程图模板
  17. 离散题目16——自反闭包
  18. 用python爬取全网百度网盘资源的神器
  19. X在苍茫大地 闻一达(闻大嘴) 闻明远
  20. 使用CityBuilder搭建智慧城市3D可视化模型

热门文章

  1. 水中浮力插件buoyancy_NaughtyWaterBuoyancy浮力插件解析
  2. XM外汇官网 xm-cnfx.com 外汇新手提高交易技巧的方法,你学会了几个?
  3. 从实战上手把手搞懂JS对象
  4. vue实战项目(每日更新打卡)
  5. stm32f103c8t6与stm32f103zet6 基于SX1276串口通信-----发送端(一)
  6. SQL Server 2012 安装过程中出现:试图执行未经授权的操作..
  7. MAC地址 的意义及作用
  8. Could not generate persistent MAC address
  9. 诺奖级成果开源!为什么说AlphaFold2足以改变全人类?
  10. php面试培训表情包,有史以来最有趣的面试表情包