Problem Description
Rompire is a robot kingdom and a lot of robots live there peacefully. But one day, the king of Rompire was captured by human beings. His thinking circuit was changed by human and thus became a tyrant. All those who are against him were put into jail, including our clever Micheal#1. Now it’s time to escape, but Micheal#1 needs an optimal plan and he contacts you, one of his human friends, for help.
The jail area is a rectangle contains n×m little grids, each grid might be one of the following: 
1) Empty area, represented by a capital letter ‘S’. 
2) The starting position of Micheal#1, represented by a capital letter ‘F’. 
3) Energy pool, represented by a capital letter ‘G’. When entering an energy pool, Micheal#1 can use it to charge his battery ONLY ONCE. After the charging, Micheal#1’s battery will become FULL and the energy pool will become an empty area. Of course, passing an energy pool without using it is allowed.
4) Laser sensor, represented by a capital letter ‘D’. Since it is extremely sensitive, Micheal#1 cannot step into a grid with a laser sensor. 
5) Power switch, represented by a capital letter ‘Y’. Once Micheal#1 steps into a grid with a Power switch, he will certainly turn it off.

In order to escape from the jail, Micheal#1 need to turn off all the power switches to stop the electric web on the roof—then he can just fly away. Moving to an adjacent grid (directly up, down, left or right) will cost 1 unit of energy and only moving operation costs energy. Of course, Micheal#1 cannot move when his battery contains no energy.

The larger the battery is, the more energy it can save. But larger battery means more weight and higher probability of being found by the weight sensor. So Micheal#1 needs to make his battery as small as possible, and still large enough to hold all energy he need. Assuming that the size of the battery equals to maximum units of energy that can be saved in the battery, and Micheal#1 is fully charged at the beginning, Please tell him the minimum size of the battery needed for his Prison break.

 
Input
Input contains multiple test cases, ended by 0 0. For each test case, the first line contains two integer numbers n and m showing the size of the jail. Next n lines consist of m capital letters each, which stands for the description of the jail.You can assume that 1<=n,m<=15, and the sum of energy pools and power switches is less than 15.
 
Output
For each test case, output one integer in a line, representing the minimum size of the battery Micheal#1 needs. If Micheal#1 can’t escape, output -1.
 
题目大意:略。太麻烦了不写了。
思路:首先此题显然可以二分答案然后判定,于是题目转化为判定问题,给定能量energy,问这个能量能否走完所有的Y。
注意到有意义的点其实只有F、G、Y,可以事先进行数次BFS,把他们之间的最短路径找出来。
注意到,Y+G不超过15,那么可以用状态压缩,记录每个点是否走过,现在在哪一个点上。用一个数组记录在某个状态下剩余的能量最多是多少。然后随便搞搞就可以水了。
PS:没有Y的时候应该是输出0吧。走到G的时候,就算没有能量了,也能充能。走到最后一个Y的时候,就算没有能量了,也能脱出。
 
代码(250MS):
 #include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
typedef long long LL; const int MAXN = << ;
const int MAXV = ; int fx[] = {-, , , };
int fy[] = {, , , -}; char mat[MAXV][MAXV];
int id[MAXV][MAXV], dis[MAXV][MAXV], Gcnt, Ycnt;
int n, m; bool isOn(int state, int i) {
return (state >> i) & ;
} int moveState(int state, int i) {
return state ^ ( << i);
} bool atEnd(int state) {
return state % ( << Ycnt) == ;
} bool isGYF(char c) {
return c == 'G' || c == 'Y' || c == 'F';
} int vis[MAXV][MAXV]; void bfsdis(int x, int y) {
memset(vis, 0x7f, sizeof(vis));
vis[x][y] = ;
queue<pair<int, int> > que;
que.push(make_pair(x, y));
int st = id[x][y];
while(!que.empty()) {
int x = que.front().first, y = que.front().second; que.pop();
if(isGYF(mat[x][y])) dis[st][id[x][y]] = vis[x][y];
for(int i = ; i < ; ++i) {
int tx = x + fx[i], ty = y + fy[i];
if(mat[tx][ty] != 'D' && vis[x][y] + < vis[tx][ty]) {
vis[tx][ty] = vis[x][y] + ;
que.push(make_pair(tx, ty));
}
}
}
} void init() {
Ycnt = ;
for(int i = ; i <= n; ++i) {
for(int j = ; j <= m; ++j) {
if(mat[i][j] != 'Y') continue;
id[i][j] = Ycnt++;
}
}
Gcnt = Ycnt;
for(int i = ; i <= n; ++i) {
for(int j = ; j <= m; ++j) {
if(mat[i][j] != 'G') continue;
id[i][j] = Gcnt++;
}
}
for(int i = ; i <= n; ++i) {
for(int j = ; j <= m; ++j) {
if(mat[i][j] != 'F') continue;
id[i][j] = Gcnt;
}
}
memset(dis, 0x7f, sizeof(dis));
for(int i = ; i <= n; ++i) {
for(int j = ; j <= m; ++j) {
if(!isGYF(mat[i][j])) continue;
bfsdis(i, j);
}
}
} int best[MAXN][MAXV];
bool inque[MAXN][MAXV]; bool check(int energy) {
memset(inque, , sizeof(inque));
memset(best, , sizeof(best));
best[( << Gcnt) - ][Gcnt] = energy;
queue<pair<int, int> > que;
que.push(make_pair(( << Gcnt) - , Gcnt));
while(!que.empty()) {
int state = que.front().first, pos = que.front().second; que.pop();
inque[state][pos] = false;
for(int i = ; i < Gcnt; ++i) {
if(!isOn(state, i)) continue;
int newState = moveState(state, i);
if(i >= Ycnt) {
if(best[state][pos] >= dis[pos][i] && best[newState][i] == ) {
best[newState][i] = energy;
inque[newState][i] = true;
que.push(make_pair(newState, i));
}
} else {
if(best[state][pos] - dis[pos][i] >= && atEnd(newState)) return true;
if(best[state][pos] - dis[pos][i] > best[newState][i]) {
best[newState][i] = best[state][pos] - dis[pos][i];
if(!inque[newState][i]) {
inque[newState][i] = true;
que.push(make_pair(newState, i));
}
}
}
}
}
return false;
} int solve() {
if(Ycnt == ) return ;
int st = Gcnt;
for(int i = ; i < Ycnt; ++i)
if(dis[i][st] > ) return -;
int l = , r = dis[st][];
for(int i = ; i < Ycnt - ; ++i) r += dis[i][i + ];
while(l < r) {
int mid = (l + r) >> ;
if(!check(mid)) l = mid + ;
else r = mid;
}
return l;
} int main() {
while(scanf("%d%d", &n, &m) != EOF) {
if(n == && m == ) break;
memset(mat, 'D', sizeof(mat));
for(int i = ; i <= n; ++i) scanf("%s", &mat[i][]);
init();
printf("%d\n", solve());
}
}

HDU 3681 Prison Break(BFS+二分+状态压缩DP)的更多相关文章

  1. HDU 3681 Prison Break 越狱(状压DP,变形)

    题意: 给一个n*m的矩阵,每个格子中有一个大写字母,一个机器人从‘F’出发,拾取所有的开关‘Y’时便能够越狱,但是每走一格需要花费1点能量,部分格子为充电站‘G’,每个电站只能充1次电.而且部分格子 ...

  2. hdu 4057 AC自己主动机+状态压缩dp

    http://acm.hdu.edu.cn/showproblem.php?pid=4057 Problem Description Dr. X is a biologist, who likes r ...

  3. HDU 3681 Prison Break(状态压缩dp + BFS)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3681 前些天花时间看到的题目,但写出不来,弱弱的放弃了.没想到现在学弟居然写出这种代码来,大吃一惊附加 ...

  4. hdu 3681 Prison Break(状态压缩+bfs)

    Problem Description Rompire . Now it’s time to escape, but Micheal# needs an optimal plan and he con ...

  5. hdu 3681 Prison Break (TSP问题)

    Prison Break Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tot ...

  6. HDU 2825 Wireless Password ( Trie图 && 状态压缩DP )

    题意 : 输入n.m.k意思就是给你 m 个模式串,问你构建长度为 n 至少包含 k 个模式串的方案有多少种 分析 : ( 以下题解大多都是在和 POJ 2778 && POJ 162 ...

  7. hdu 5067 Harry And Dig Machine (状态压缩dp)

    题目链接 bc上的一道题,刚开始想用这个方法做的,因为刚刚做了一个类似的题,但是想到这只是bc的第二题, 以为用bfs水一下就过去了,结果MLE了,因为bfs的队列里的状态太多了,耗内存太厉害. 题意 ...

  8. HDU 5418 Victor and World (状态压缩dp)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5418 题目大意:有n个结点m条边(有边权)组成的一张连通图(n <16, m<100000 ...

  9. HDU 4649 Professor Tian(反状态压缩dp,概率)

    本文出自   http://blog.csdn.net/shuangde800 题目链接:点击打开链接 题目大意 初始有一个数字A0, 然后给出A1,A2..An共n个数字,这n个数字每个数字分别有一 ...

随机推荐

  1. [dpdk] 读官方文档(2)

    续前节.切好继续: 一,文档里提到uio_pci_generic, igb_uio, vfio_pci三个内核模块,完全搞不懂,以及dpdk-devbind.py用来查看网卡状态,我得到了下边的输出: ...

  2. ubuntu 64bit arm-linux-gcc: No such file or directory 解决

    通过下面这个解决 ubuntu 64bit  arm-linux-gcc: No such file or directory 安装 sudo apt-get install lsb-core解决 h ...

  3. (转)常用的js设计模式

    模式是解决或者避免一些问题的方案. 在JavaScript中,会用到一些常用的编码模式.下面就列出了一些常用的JavaScript编码模式,有的模式是为了解决特定的问题,有的则是帮助我们避免一些Jav ...

  4. 文件对比工具Beyond Compare使用方法

    今天向大家介绍一个使用起来十分方便且功能十分强大的文件对比工具-Beyond Compare. 1    工具下载 工具的下载很简单,百度搜索Beyond Compare即可. 下载完成后,解压缩,双 ...

  5. NRF51822之GPIOTE使用

    ---恢复内容开始--- 在上篇介绍nrf51822的GPIOTE http://www.cnblogs.com/libra13179/p/5336580.html 我们现在开始下水游泳. /** @ ...

  6. Android源码剖析之Framework层升级版(窗口、系统启动)

    本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处! 看本篇文章之前,建议先查看: Android源码剖析之Framework层基础版 前面讲了frame ...

  7. 【Android测试】【第三节】ADB——源码浅谈

    ◆版权声明:本文出自carter_dream的博客,转载必须注明出处. 转载请注明出处:http://www.cnblogs.com/by-dream/p/4651724.html 前言 由于本人精力 ...

  8. Bulk Insert & BCP执行效率对比(续)

    上回由于磁盘空间(约70G)不足,导致Bulk Insert和BCP导入中途失败:今次统一一些操作,以得到Bulk insert与BCP分别执行效率: 1. 15435390笔数据,21.7G csv ...

  9. linux epoll 简单demo

    一个简单的epoll demo ,同时接受多个客户端连接,并把接收到的字符串转化为大写字母返回给客户端 #include<stdio.h> #include<arpa/inet.h& ...

  10. angularJS平行控制器间共享数据

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...