HDU 3681 Prison Break(状压DP + BFS)题解
题意:一张图,F是起点,Y是必须要到的点,D不能走,G可以充电。可以往四个方向走,每走一步花费一个电,走到G可以选择充满电或者不充,每个G只能充一次。问你走遍Y的最小初始点亮。number(G) + number(Y) <= 15
思路:显然Y和G都只要用一次就行,那么状压YG状态。然后BFS出任意YG两点最短路,状压DP。用&判断最终结果是不是当前状态的子集。
代码:
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include <iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 15;
const int M = maxn * 30;
const ull seed = 131;
const int INF = 0x3f3f3f3f;
const int MOD = 1e4 + 7;
int dp[1 << maxn][maxn];
char mp[maxn + 10][maxn + 10];
int n, m, sx, sy;
int cnt;
int id[maxn * maxn + 20];
int bettery[maxn * maxn + 20];
int getid(int x, int y){
return id[x * m + y];
}
struct Node{
int x, y, step;
};
int dis[maxn * maxn + 10][maxn * maxn + 10];
int vis[maxn + 5][maxn + 5];
int to[4][2] = {0, 1, 0, -1, 1, 0, -1, 0};
void bfs(int x, int y){
memset(vis, 0, sizeof(vis));
Node a, b;
queue<Node> q;
while(!q.empty()) q.pop();
vis[x][y] = 1;
a.x = x, a.y = y, a.step = 0;
q.push(a);
while(!q.empty()){
a = q.front();
q.pop();
if(mp[a.x][a.y] != 'D' && mp[a.x][a.y] != 'S') dis[getid(x, y)][getid(a.x, a.y)] = a.step;
for(int i = 0; i < 4; i++){
b.x = a.x + to[i][0];
b.y = a.y + to[i][1];
if(b.x < 0 || b.y < 0 || b.x >= n || b.y >= m) continue;
if(vis[b.x][b.y]) continue;
if(mp[b.x][b.y] == 'D') continue;
vis[b.x][b.y] = 1;
b.step = a.step + 1;
q.push(b);
}
}
} int Fin;
bool check(int st){
memset(dp, -1, sizeof(dp));
for(int i = 0; i < cnt; i++){
if(dis[cnt][i] <= st){
if(bettery[i]) dp[1 << i][i] = st;
else dp[1 << i][i] = st - dis[cnt][i];
}
} for(int i = 0; i < (1 << cnt); i++){
for(int j = 0; j < cnt; j++){
if(dp[i][j] == -1) continue;
if(!((1 << j) & i)) continue;
if((i & Fin) == Fin) return true;
for(int k = 0; k < cnt; k++){
if((1 << k) & i) continue;
if(dis[j][k] > dp[i][j]) continue;
dp[i | (1 << k)][k] = max(dp[i][j] - dis[j][k], dp[i | (1 << k)][k]);
if(bettery[k]) dp[i | (1 << k)][k] = st;
}
}
} return false;
} int main(){
while(~scanf("%d%d", &n, &m) && n + m){
cnt = 0;
Fin = 0;
int tmp = 0;
memset(bettery, 0, sizeof(bettery));
for(int i = 0; i < n; i++){
scanf("%s", mp[i]);
for(int j = 0; j < m; j++){
if(mp[i][j] == 'F'){
sx = i, sy = j;
}
else if(mp[i][j] == 'G'){
bettery[cnt] = 1;
id[i * m + j] = cnt++;
}
else if(mp[i][j] == 'Y'){
Fin += (1 << cnt);
id[i * m + j] = cnt++;
tmp++;
}
}
}
id[sx * m + sy] = cnt; if(tmp == 0){
printf("0\n");
continue;
} memset(dis, INF, sizeof(dis));
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
if(mp[i][j] != 'D' && mp[i][j] != 'S')
bfs(i, j);
}
} int l = 0, r = 1000000;
int ans = -1;
while(l <= r){
int m = (l + r) >> 1;
if(check(m)){
r = m - 1;
ans = m;
}
else l = m + 1;
}
printf("%d\n", ans);
}
return 0;
}
HDU 3681 Prison Break(状压DP + BFS)题解的更多相关文章
- hdu 3247 AC自动+状压dp+bfs处理
Resource Archiver Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 100000/100000 K (Java/Ot ...
- HDU 4272 LianLianKan(状压DP)题解
题意:一个栈,每次可以选择和栈顶一样的数字,并且和栈顶距离小于6,然后同时消去他们,问能不能把所有的数消去 思路:一个数字最远能消去和他相距9的数,因为中间4个可以被他上面的消去.因为还要判断栈顶有没 ...
- HDU 4628 Pieces(状压DP)题解
题意:n个字母,每次可以删掉一组非连续回文,问你最少删几次 思路:把所有回文找出来,然后状压DP 代码: #include<set> #include<map> #includ ...
- hdu 2825 aC自动机+状压dp
Wireless Password Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others ...
- BZOJ_3049_[Usaco2013 Jan]Island Travels _状压DP+BFS
BZOJ_3049_[Usaco2013 Jan]Island Travels _状压DP+BFS Description Farmer John has taken the cows to a va ...
- HDU 3247 Resource Archiver(AC自动机 + 状压DP + bfs预处理)题解
题意:目标串n( <= 10)个,病毒串m( < 1000)个,问包含所有目标串无病毒串的最小长度 思路:貌似是个简单的状压DP + AC自动机,但是发现dp[1 << n][ ...
- HDU 5765 Bonds(状压DP)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5765 [题目大意] 给出一张图,求每条边在所有边割集中出现的次数. [题解] 利用状压DP,计算不 ...
- hdu 4778 Gems Fight! 状压dp
转自wdd :http://blog.csdn.net/u010535824/article/details/38540835 题目链接:hdu 4778 状压DP 用DP[i]表示从i状态选到结束得 ...
- HDU 4272 LianLianKan (状压DP+DFS)题解
思路: 用状压DP+DFS遍历查找是否可行.假设一个数为x,那么他最远可以消去的点为x+9,因为x+1~x+4都能被他前面的点消去,所以我们将2进制的范围设为2^10,用0表示已经消去,1表示没有消去 ...
随机推荐
- 输入12V,输出12V的限流芯片
随着手机充电电流的提升,和设备的多样化,USB限流芯片就随着需求的增加而越来越多,同时为了更好的保护电子设备,需要进行一路或者多路的负载进行限流. USB限流芯片,5V输入 1, PW1502,常使用 ...
- 2021年【线上】第一性原理vasp技术实战培训班
材料模拟分子动力学课程 3月19号--22号 远程在线课 lammps分子动力学课程 3月12号--15号 远程在线课 第一性原理VASP实战课 3月25号-28号 远程在线课 量子化学Gaussia ...
- 【1w字+干货】第一篇,基础:让你的 Redis 不再只是安装吃灰到卸载(Linux环境)
Redis 基础以及进阶的两篇已经全部更新好了,为了字数限制以及阅读方便,分成两篇发布. 本篇主要内容为:NoSQL 引入 Redis ,以及在 Linux7 环境下的安装,配置,以及总结了非常详细的 ...
- SpringBoot 报错: Circular view path [readingList] 解决办法
spring boot报错: Circular view path [readingList]: would dispatch back to the current handler URL [/re ...
- (Oracle)数据量统计存储过程
本过程适用于Oracle数据量统计. create or replace procedure SP_GET_TAB_COUNT as v_tableName HDSD_TJ.Tablename%typ ...
- Spring框架——AOP面向切面编程
简介 AOP练习 使用动态代理解决问题 Spring AOP 用AspectJ注解声明切面 前置后置通知 利用方法签名编写AspectJ切入点表达式 指定切面的优先级 基于XML的配置声明切面 Spr ...
- Spark踩坑填坑-聚合函数-序列化异常
Spark踩坑填坑-聚合函数-序列化异常 一.Spark聚合函数特殊场景 二.spark sql group by 三.Spark Caused by: java.io.NotSerializable ...
- yuan先生博客地址
1 Web应用 https://www.cnblogs.com/yuanchenqi/articles/8869302.html2 http协议 https://www.cnblogs.com/yu ...
- 25.sshd和scp
1.配置sshd服务 想要使用 SSH 协议来远程管理Linux 系统,则需要部署配置sshd 服务程序.sshd 是基于SSH协议开发的一款远程管理服务程序. sshd 服务的配置信息保存在/e ...
- 虚拟局域网(VLAN)__语音VLAN
1.语音VLAN特性使得访问端口能够携带来自IP电话的IP语音流量.当交换机连接到Cisco IP电话时,IP电话就用第3层IP优先级(precedence)和第2层服务级别(class of ser ...