题目大意:有一个机器人想越狱,越狱的要求是将所有的电网开关关掉。现在给出一个地图,’S’表示空地,‘F‘表示起始地点,‘G‘表示充电池,‘D‘表示禁地,‘Y‘开关
充电池可以将机器人的电充满。机器人每走一格就需要耗掉1点能量,问机器人的起始能量至少要是多少才可以逃出监狱

解题思路:先将所有能连通的点连通起来,将充电池和开关抽象出来,压缩成一个状态
求出每个充电池和开关之间的两两间的最短距离,接着二分枚举机器人的初始电量,再暴力枚举机器人行动的每种情况(dfs)

这里已经求出了充电池和开关之间的最短距离了,那怎样判断经过了充电池是否要充电呢
因为枚举的时候,是只枚举机器人到充电池和开关的最短路径的,如果中途遇到了充电池,也就是说最短路的路途中有充电池,这种情况经过是不进行充电的
而如果是枚举的下一点是充电池的话,这种情况是直接充电的
这样就把经过充电池该不该充电的情况给考虑进去了

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#define N 20
#define M 410
#define S 2010char g[N][N];
int head[M], u[S], v[S],  Next[S], id[N][N], dis[N][N], x[N], y[N];
int n, m, num, cnt, final;void add_edgs(int s, int e) {u[cnt] = s;v[cnt] = e;Next[cnt] = head[s];head[s] = cnt++;
}void init() {memset(head, -1, sizeof(head));memset(id, -1, sizeof(id));memset(dis, -1, sizeof(dis));cnt = 0; num = 1; final = 0;for (int i = 0; i < n; i++)scanf("%s", g[i]);for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {if (g[i][j] == 'D')continue;else if (g[i][j] == 'F') {x[0] = i;y[0] = j;id[i][j] = 0;}else if (g[i][j] == 'G') {x[num] = i;y[num] = j;id[i][j] = num++;}else if (g[i][j] == 'Y') {x[num] = i;y[num] = j;final |= (1 << num);id[i][j] = num++;}if (i > 0 && g[i - 1][j] != 'D')add_edgs(i * m + j, (i - 1) * m + j);if (j > 0 && g[i][j - 1] != 'D')add_edgs(i * m + j, i * m + j - 1);if (i + 1 < n && g[i + 1][j] != 'D')add_edgs(i * m + j, (i + 1)* m + j);if (j + 1 < m && g[i][j + 1] != 'D')add_edgs(i * m + j, i * m + j + 1);}}
}
struct Node {int pos, dis;
}n1, n2;bool vis[M];
void bfs(int s) {queue<struct Node> q;memset(vis, 0, sizeof(vis));n1.pos = s;n1.dis = 0;q.push(n1);vis[s] = 1;while (!q.empty()) {n2 = q.front();q.pop();int t = n2.pos;if (id[t / m][t % m] != -1)dis[id[t / m][t % m]][id[s / m][s % m]] = n2.dis;for (int i = head[t]; i != -1; i = Next[i]) {if (vis[v[i]])continue;n1.pos = v[i];n1.dis = n2.dis + 1;q.push(n1);vis[v[i]] = 1;}}
}bool mark[N];
bool dfs(int pos, int state, int power, int all_power) {if ((state & final) == final)return true;for (int i = 1; i < num; i++) {if (mark[i] || dis[pos][i] == -1)continue;if (power >= dis[pos][i]) {if (g[x[i]][y[i]] == 'G') {mark[i] = 1;if (dfs(i, state | (1 << i), all_power, all_power))return true;mark[i] = 0;}else {mark[i] = 1;if (dfs(i, state | (1 << i), power - dis[pos][i], all_power))return true;mark[i] = 0;}}}return false;
}void solve() {for (int i = 0; i < num; i++)bfs(x[i] * m + y[i]);bool flag = false;int ans = -1;for (int i = 1; i < num; i++)if (g[x[i]][y[i]] == 'Y' && dis[id[x[i]][y[i]]][0] == -1) {flag = true;break;}if (!flag) {int l = 0, r = n * m * (num - 1);while (l <= r) {int mid = (l + r) / 2;memset(mark, 0, sizeof(mark));mark[0] = 1;if (dfs(0, 1, mid, mid)) {ans = mid;r = mid - 1;}else {l = mid + 1;}}}printf("%d\n", ans);
}int main() {while (scanf("%d%d", &n, &m) != EOF && n + m) {init();solve();}return 0;
}

HDU - 3681 Prison Break(状态压缩 + 最短路)相关推荐

  1. hdu 3681(bfs+dfs+状态压缩)

    解题思路:这道题属于图上来回走的问题,可以把重复走的过程弱化,即只强调从u->v的结果,中间经过的节点都不考虑.这道题里面'G','F','Y'是重要的节点,其余的点我们是可以忽略的,也就是说, ...

  2. 区域判断hdu 3681 Prison Break bfs+二分+dp

    时间紧张,先记一笔,后续优化与完善. 这个是2010杭州区域赛的目题. bfs出最短路,二分谜底,dp判断可行性. #include <iostream> #include <cst ...

  3. HDU 4407 Sum(容斥原理+状态压缩)

    题目链接 容斥原理不会,map不会,状态压缩不会.做毛线... 题目大意:给出1-n,n个数,有两个操作1是询问x-y区间上与p互质的数的和是多少,2是改变x位置上的数为c. 自己确实办不了,map这 ...

  4. HDU 4997 Biconnected (状态压缩DP)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=4997 题意:一个n个点的完全图中去掉一些边.求这个图有多少个子图是边双联通的.(就是去掉任意一条边之后 ...

  5. HDU 4332 Constructing Chimney [状态压缩+矩阵]

    烟囱是一个3*3的中空构造,给定烟囱的高度,问用1*1*2的砖头搭成这个烟囱有多少种方法. 首先用一个8位二进制数表示某一层的状态.枚举上下两层的状态,判断这两个状态是否可以相邻,上一层必须将下层填满 ...

  6. [HDU 4842]--过河(dp+状态压缩)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4842 过河 Time Limit: 3000/1000 MS (Java/Others)    Mem ...

  7. HDU 4921 Map(状态压缩)

    题意看这篇博客. 思路参考的这篇博客. 补充:面对这种问题有一个常见的套路.比如计算若干个区间对答案的贡献这种问题,直接暴力可能复杂度到O(n ^ 2), 而我们可以计算出每个元素在多少个合法区间中, ...

  8. HDU - 6749 Mosquito(二分+状态压缩+最大流)

    题目链接:点击查看 题目大意:给出一个 n * m 的房间,再给出 k 个蚊子窝(保证蚊子窝在边界上),每个蚊子窝内有数只蚊子,单位时间内蚊子可以移动一个单位的曼哈顿距离,蚊子们都是非常聪明的,问最少 ...

  9. HDU 1557 权利指数 国家压缩 暴力

    HDU 1557 权利指数 状态压缩 暴力 ACM 题目地址:HDU 1557 权利指数 题意:  中文题,不解释. 分析:  枚举全部集合,计算集合中的和,推断集合里面的团体是否为关键团队. 代码: ...

最新文章

  1. nginx多进程,日志不乱序
  2. 微信发布2017国庆长假出游情况大数据报告
  3. Google服务器 IP
  4. 构建Java Web开发环境
  5. 【Java学习笔记二】继承和多态
  6. python输出运行时间_分析python程序运行时间的几种方法
  7. Linux上Oracle自动启停方案
  8. iOS开发常见的宏定义(实用)
  9. 计算机自动化考试试题,计算机等级考试,办公自动化考试试题(一).doc
  10. Web全栈工程师应该会什么
  11. Linux自学,第一天
  12. SpringBoot+Vue项目网上家电商城
  13. docker配置国内加速器的两种方法
  14. 什么是大数据,大数据最缺什么样的人才?
  15. python3 字符和数字(ASC码)转换
  16. PyCharm的安装与使用
  17. 19-05【icloud】照片备份
  18. 安卓文件传输工具 Android File Transfer mac
  19. GTD时间管理 | 高效能人士的工作习惯
  20. C. Chocolate Bunny

热门文章

  1. RSS从入门到精通(转载)
  2. Python个人主页项目-2.项目创建与环境配置
  3. AutoJs学习-投币小游戏
  4. MSP430F5529LP 2022电赛学习准备及相关例程
  5. Android学习笔记-recreate()方法导致fragment重复新建的问题,解决方法
  6. 智慧城市App解决方案
  7. BZOJ 4864: [BeiJing 2017 Wc]神秘物质 解题报告
  8. Ansible 下载模块get_url、解压缩模块unarchive(学习笔记十五)
  9. 【U8】禁止UU(UTU)随登陆账套启动(U8V11.0及其以上版本)
  10. Win10系统设置炫酷下拉关机(其实很简单啦!)