HDU 3681 * Break(BFS+二分+状态压缩DP)

时间:2022-02-19 00:20:51
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 * 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 * Break(BFS+二分+状态压缩DP)的更多相关文章

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

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

  2. hdu 4057 AC自己主动机&plus;状态压缩dp

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

  3. HDU 3681 * Break(状态压缩dp &plus; BFS)

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

  4. hdu 3681 * Break&lpar;状态压缩&plus;bfs&rpar;

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

  5. hdu 3681 * Break (TSP问题)

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

  6. HDU 2825 Wireless Password &lpar; Trie图 &amp&semi;&amp&semi; 状态压缩DP &rpar;

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

  7. hdu 5067 Harry And Dig Machine &lpar;状态压缩dp&rpar;

    题目链接 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. javascript设计模式与开发实践阅读笔记(5)——策略模式

    策略模式:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换. 我的理解就是把各种方法封装成函数,同时存在一个可以调用这些方法的公共函数.这样做的好处是可以消化掉内部的分支判断,使代码效率 ...

  2. Java Web基础——Action&plus;Service &plus;Dao三层的功能划分

    1. Action/Service/DAO简介: Action是管理业务(Service)调度和管理跳转的. Service是管理具体的功能的. Action只负责管理,而Service负责实施. D ...

  3. hdfs 集群间拷贝

    hadoop distcp -i hdfs://192.168.10.211:9000/fileinfo hdfs://192.168.24.46:9000/fileinfo distcp [OPTI ...

  4. Ubuntu 14&period;04下安装Hadoop2&period;4&period;0 (单机模式)

    转自 http://www.linuxidc.com/Linux/2015-01/112370.htm 一.在Ubuntu下创建Hadoop组和hadoop用户 增加hadoop用户组,同时在该组里增 ...

  5. Inside The C&plus;&plus; Object Model - 02

    前言 - 什么是C++对象模型 C++对象模型包括2个方面的含义: 1.语言中直接支持面向对象程序设计的部分 2.对于各种(面向对象)支持的底层实现机制. 无论是什么语言,都需要转换为汇编.很多面向对 ...

  6. Entity Framework 学习笔记(一)安装

    1.通过 VS2013 下载,这个没有限制,因为我用的vs是2013 Entity Framework包

  7. ValueError&colon; Attempted relative import in non-package

    执行:python deom/scripts/populate.py ValueError: Attempted relative import in non-package solve:python ...

  8. 传感器仿真平台——UI绘制模块(二)

    这一章讲的是UI绘制模块 该模块的作用是将实验对象绘制出来,它可能是目标.传感器等等,由于事先并不知道会有哪些物体,也无法事先定义好某个对象该怎么画,以我懒人的性格,得了,就抛给用的人吧~喝前摇一摇, ...

  9. SQL---约束---add constraint方法添加约束

    1.主键约束: 格式为:alter table 表格名称 add constraint 约束名称 增加的约束类型 (列名) 例子:alter table emp add constraint ppp ...

  10. 做为一个Python程序员的基本素养

    今天在学习的过程中,明白了一些不是Python标准所必须要做的事情,二是做为一个合格的Python程序员应该所遵从的一些规范 分享给大家,有不足的地方请大家指正,此下是我学习的一点心得: 1.在给变量 ...