题意:一张图,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)题解的更多相关文章

  1. hdu 3247 AC自动+状压dp+bfs处理

    Resource Archiver Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 100000/100000 K (Java/Ot ...

  2. HDU 4272 LianLianKan(状压DP)题解

    题意:一个栈,每次可以选择和栈顶一样的数字,并且和栈顶距离小于6,然后同时消去他们,问能不能把所有的数消去 思路:一个数字最远能消去和他相距9的数,因为中间4个可以被他上面的消去.因为还要判断栈顶有没 ...

  3. HDU 4628 Pieces(状压DP)题解

    题意:n个字母,每次可以删掉一组非连续回文,问你最少删几次 思路:把所有回文找出来,然后状压DP 代码: #include<set> #include<map> #includ ...

  4. hdu 2825 aC自动机+状压dp

    Wireless Password Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  5. 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 ...

  6. HDU 3247 Resource Archiver(AC自动机 + 状压DP + bfs预处理)题解

    题意:目标串n( <= 10)个,病毒串m( < 1000)个,问包含所有目标串无病毒串的最小长度 思路:貌似是个简单的状压DP + AC自动机,但是发现dp[1 << n][ ...

  7. HDU 5765 Bonds(状压DP)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5765 [题目大意] 给出一张图,求每条边在所有边割集中出现的次数. [题解] 利用状压DP,计算不 ...

  8. hdu 4778 Gems Fight! 状压dp

    转自wdd :http://blog.csdn.net/u010535824/article/details/38540835 题目链接:hdu 4778 状压DP 用DP[i]表示从i状态选到结束得 ...

  9. HDU 4272 LianLianKan (状压DP+DFS)题解

    思路: 用状压DP+DFS遍历查找是否可行.假设一个数为x,那么他最远可以消去的点为x+9,因为x+1~x+4都能被他前面的点消去,所以我们将2进制的范围设为2^10,用0表示已经消去,1表示没有消去 ...

随机推荐

  1. 在.NET Core 中使用Quartz.NET

    Quartz.NET是功能齐全的开源作业调度系统,可用于最小的应用程序到大型企业系统. Quartz.NET具有三个主要概念: job:运行的后台任务 trigger:控制后台任务运行的触发器. sc ...

  2. 特征预处理之归一化&标准化

    写在前面 这篇博客的主要内容 应用MinMaxScaler实现对特征数据进行归一化 应用StandardScaler实现对特征数据进行标准化 特征预处理 定义 ​ 通过一些转换函数将特征数据转换成更加 ...

  3. 给HTML页面设置自己的icon

    原因: 不知道为什么,SpringBoot中自动设置icon失效了. 解决方法: 在head标签中添加自己想要使用的icon图片.后缀使用图片格式,不要使用.ico. <link href=&q ...

  4. LocalDateTime、OffsetDateTime、ZonedDateTime互转,这一篇绝对喂饱你

    前言 你好,我是A哥(YourBatman). 在JSR 310日期时间体系了,一共有三个API可用于表示日期时间: LocalDateTime:本地日期时间 OffsetDateTime:带偏移量的 ...

  5. 今天聊点干货—关于CSS样式来源

    样式来源 CSS样式共有5个来源,它们分别是\(\color{#FF3030}{浏览器默认样式}\).\(\color{#FF3030}{用户样式}\).\(\color{#FF3030}{链接样式} ...

  6. Vue基础之Vue组件

    Vue基础之Vue组件 // 组件是可以复用的Vue实例! // 可以把经常重复的功能封装为组件!

  7. Jmeter接口自动化测试系列之函数使用及扩展

    介绍一下Jmeter自带函数的使用和 函数扩展,来满足测试工作中的各种需求! Jmeter自带函数 点击函数帮助助手图标,弹出函数助手框,可以选择各种各样的函数 举例: _Random 获取随机数,可 ...

  8. vscode 远程开发安装

    1 首先windows 有ssh  程序 2 没有的话就直接使用git  bash 登录到远程服务器开发机上 3 再开一个Git bash  执行 ssh-keygen.exe   生成秘钥    然 ...

  9. Python学习【第8篇】:python中的函数

    1.python中函数定义方法 def test(x): "This istest" y = x*2+1 return y vaule = test(2)print(vaule)运 ...

  10. Eclipse插件springsource-tool-suite的下载和安装

    根据佟刚Spring课程,装完这个插件,再利用maven构建工程,爽 课程:https://www.bilibili.com/video/av21335209?from=search&seid ...