题目链接:hdu 5440 Clock Adjusting

解题思路

卡着时间AC的,双向bfs,根据指向1,2…,12的clock个数建立hash函数,从终止状态逆向搜索5步,从起始状态正向搜索3步(因为终止状态对应的都是12,所以转移起来状态相对起始状态要少一些)

使用tool的顺序是无关紧要的,所以在搜索时,考虑到状态s,是通过使用前i个tool转移过来的,那么只需要在考虑使用i,i+1…,M即可(这里我优先使用编号大的tool,不确定有没有优化的作用)

在确定状态s和工具i后,需要枚举修改哪些clock,一开始我是用二进制状态表示需要被修改的地方,但是重复的太多,就用dfs+剪枝枚举。

这题应该还有更厉害的优化,我是卡1400Ms过的。

代码

#include <cstdio>
#include <cstring>
#include <set>
#include <map>
#include <vector>
#include <queue>
#include <algorithm>using namespace std;
typedef long long ll;
const int maxn = 1 * 1e5 + 5;ll S;
int N, M, L[10], X[10], head, rear, ans;
map<ll, int> C;
set<ll> T;struct State {ll s;int f, c;State(ll s = 0, int f = 0, int c = 0): s(s), f(f), c(c) {}
}Q[maxn], cur;inline ll idx(int* c) {ll ret = 0;for (int i = 0; i < 12; i++)ret = ret * (N+1) + c[i];return ret;
}inline void reidx(ll s, int* c) {for (int i = 11; i >= 0; i--) {c[i] = s % (N+1);s /= (N+1);}
}void init () {C.clear();T.clear();scanf("%d%d", &N, &M);int x, cnt[15];memset(cnt, 0, sizeof(cnt));for (int i = 1; i <= N; i++) {scanf("%d", &x);if (x == 12) x = 0;cnt[x]++;}S = idx(cnt);for (int i = 0; i < M; i++)scanf("%d%d", &L[i], &X[i]);
}bool dfs1 (int d, int* c, int* t, int n, int m, int v) {if (d > 12 || n > m) return false;if (n == 0 && m == 0) {ll tmp = idx(t);if (tmp == S) {ans = cur.c + 1;return true;}if (!C.count(tmp)) {C[tmp] = cur.c + 1;if (cur.c < 4) Q[rear++] = State(tmp, v, cur.c+1);}return false;}for (int i = min(c[d], n); i >= 0; i--) {if (n-i > m-c[d]) break;t[(d-X[v]+12)%12] += i;t[d] += (c[d] - i);if (dfs1(d+1, c, t, n-i, m-c[d], v)) return true;t[(d-X[v]+12)%12] -= i;t[d] -= (c[d] - i);}return false;
}bool dfs2 (int d, int* c, int* t, int n, int m, int v) {if (d > 12 || n > m) return false;if (n == 0 && m == 0) {ll tmp = idx(t);if (C.count(tmp)) {ans = C[tmp] + cur.c + 1;return true;}if (!T.count(tmp) && cur.c < 2) {T.insert(tmp);Q[rear++] = State(tmp, v, cur.c+1);}return false;}for (int i = min(c[d], n); i >= 0; i--) {if (n-i > m-c[d]) break;t[(d+X[v]+12)%12] += i;t[d] += (c[d] - i);if (dfs2(d+1, c, t, n-i, m-c[d], v)) return true;t[(d+X[v]+12)%12] -= i;t[d] -= (c[d] - i);}return false;
}int bfs() {int cnt[15], pos[15];memset(cnt, 0, sizeof(cnt));cnt[0] = N;ll k = idx(cnt);if (S == k) return 0;C[k] = 0;head = rear = 0;for (int i = 0; i < M; i++) {int x = (-X[i] + 12) % 12;cnt[x] += L[i];cnt[0] -= L[i];ll tmp = idx(cnt);if (!C.count(tmp)) {if (tmp == S) return 1;Q[rear++] = State(tmp, i, 1);C[tmp] = 1;}cnt[x] -= L[i];cnt[0] += L[i];}while (head < rear) {cur = Q[head++];reidx(cur.s, cnt);for (int i = M-1; i >= cur.f; i--) {memset(pos, 0, sizeof(pos));if (dfs1(0, cnt, pos, L[i], N, i))return ans;}}head = rear = 0;Q[rear++] = State(S, 0, 0);while (head < rear) {cur = Q[head++];reidx(cur.s, cnt);for (int i = M-1; i >= cur.f; i--) {memset(pos, 0, sizeof(pos));if (dfs2(0, cnt, pos, L[i], N, i)) return ans;}}return -1;
}int main () {int cas;scanf("%d", &cas);while (cas--) {init();printf("%d\n", bfs());}return 0;
}

hdu 5440 Clock Adjusting(双向bfs)相关推荐

  1. 专题训练二 搜索进阶 HDU - 3085 Nightmare Ⅱ (双向BFS + 曼哈顿距离)

    HDU - 3085 Nightmare Ⅱ (双向BFS + 曼哈顿距离) Problem Description Last night, little erriyue had a horrible ...

  2. HDU 1043 Eight(双向BFS+康托展开)

    http://acm.hdu.edu.cn/showproblem.php?pid=1043 题意:给出一个八数码,求出到达指定状态的路径. 思路:路径寻找问题.在这道题里用到的知识点挺多的.第一次用 ...

  3. HDU - 3085 Nightmare Ⅱ(双向bfs)

    题目链接:点击查看 题目大意:给出一个迷宫,一个男孩和一个女孩还有两只鬼,男孩每秒钟走3格,女孩每秒钟走1格,鬼每秒钟向四周分裂2格,问男孩和女孩能否在鬼占领迷宫之前汇合,能的话输出汇合时间,否则输出 ...

  4. hdu 3567(八码数 + 双向bfs)

    题目连接:https://vjudge.net/contest/353606#problem/B 参考文章:https://blog.csdn.net/laaahu/article/details/9 ...

  5. HDU3085 Nightmare Ⅱ —— 双向BFS + 曼哈顿距离

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3085 Nightmare Ⅱ Time Limit: 2000/1000 MS (Java/Other ...

  6. 浅谈迷宫搜索类的双向bfs问题(例题解析)

    文章目录 前言 bfs类问题 双向bfs 例题实战 前言 文章若有疏忽还请指正,更多精彩还请关注公众号:bigsai 在搜索问题中,以迷宫问题最具有代表性,无论是八皇后的回溯问题,还是dfs找出口,b ...

  7. [题解](双向bfs)hdu_3085_Nightmare Ⅱ

    发现直接搜索比较麻烦,但是要同时两个人一起走容易想到双向bfs,比较普通, 在判断是否碰到ghost时只要比较两点的曼哈顿距离大小和step*2(即ghost扩散的距离)即可,仔细思考也是可以想到的 ...

  8. UVA1601The Morning after Halloween 单向加双向bfs

    题意:w*h(w,h16)网格上有n(n3)个小写字母(代表鬼).要求把它们分别移动到对应的大写字母里.每步可以有多个鬼同时移动(均为往上下左右四个方向之一移动),但每步结束之后任何两个鬼不能占用同一 ...

  9. [蓝桥杯][历届试题]九宫重排-双向bfs和map标记

    题目描述 如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着.与空格子相邻的格子中的卡片可以移动到空格中.经过若干次移动,可以形成第二个图所示的局面. 我们把第一个图的局面记为:12 ...

  10. 走迷宫-双向bfs解法

    双向bfs适用于知道起点和终点的状态下使用,从起点和终点两个方向开始进行搜索,可以非常大的提高单个bfs的搜索效率 同样,实现也是通过队列的方式,可以设置两个队列,一个队列保存从起点开始搜索的状态,另 ...

最新文章

  1. python3高级语法:__slots__属性、property装饰器、上下文管理协议、__new__方法
  2. JavaFX——JavaFX概览
  3. 100篇精选算法技术文章收藏
  4. 硅谷渐患“大城市”病,世界创新中心或将外移...
  5. tomcat(4)Tomcat的默认连接器
  6. 安装nginx并搭建nginx图片服务器
  7. PHP数据结构预热:PHP的迭代器(转)
  8. 为何python不好找工作-听说自学Python不好找工作,小白要如何学Python?
  9. 2019.1.15 作业
  10. B/S系统间跨域单点登录设计思路
  11. c语言乘法除法结合律,有关C语言运算符优先级和结合律的思考
  12. Docker从理论到实践(六)------搭建和使用本地私有Docker镜像仓库
  13. windows-提权常用技巧总结
  14. [学习IMU](MEMS 三轴加速计、三轴陀螺仪、三轴磁力计)6轴IMU+磁力计,9轴传感器讲解
  15. linux下对SD卡分区
  16. Pytorch实现GPU和TPU运算
  17. 35岁的程序员何去何从?--记PMP考试感悟
  18. 【考研英语】作文套话(自用)
  19. 魅族 刷机android 6.0,乐视X900+安卓6.0 魅族Flyme6刷机包 最新6.7.12.29R付费纯净版
  20. 使用java计算数组方差和标准差

热门文章

  1. get,post请求实例
  2. 通达信自定义副图换手率指标 HSL_QD
  3. 2021年全球与中国直升飞机行业市场规模及发展前景分析
  4. [系统] 电脑突然变卡 / 电脑突然** / 各种突发情况解决思路
  5. 英语每日听写练习 Day 15
  6. 平安科技hr核人面试问什么_为什么在下次科技公司面试时会问问题
  7. ROS笔记(三)用键盘控制模型在gazebo中移动
  8. css3 rotate360度自转
  9. R语言使用epiDisplay包的clogistic.display函数获取条件logistic回归模型的汇总统计信息(自变量初始和调整后的优势比及置信区间,回归系数的Wald检验的p值)、保存csv
  10. 从js的dtree说起