也算难题,难在如何处理有些点可以无限次经过 问题。 这道题,其实很容易想到二分+TSP的状态压缩,但在处理上述问题时,确实没想到。题解是处理每一个Y或G或F点到其他YGF点的距离,BFS,这样就出现一个点只访问一次,而且即便在原图上重复经过某点,在重建的图也不会体现出来了。绝!

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; char map[16][16];
bool vis[16][16];
int cnt,dp[1<<16][16];
struct Node{
int x,y;
}node[16];
int dis[16][16][16][16];
const int inf=(1<<30);
int n,m,fp,head,tail;
int dir[4][2]={
{0,1},
{0,-1},
{1,0},
{-1,0}
};
Node que[400];
int endfor; bool ok(int x,int y){
if(x>=0&&x<n&&y>=0&&y<m&&map[x][y]!='D'&&!vis[x][y]) return true;
return false;
} void bfs(Node start){
Node tmp;
vis[start.x][start.y]=true;
que[tail++]=start;
int step=0;
while(head<tail){
int sz=tail-head;
step++;
while(sz--){
Node ss=que[head++];
for(int i=0;i<4;i++){
tmp.x=ss.x+dir[i][0];
tmp.y=ss.y+dir[i][1];
if(ok(tmp.x,tmp.y)){
if(map[tmp.x][tmp.y]=='G'||map[tmp.x][tmp.y]=='Y'){
dis[start.x][start.y][tmp.x][tmp.y]=step;
// cout<<start.x<<" "<<start.y<<" "<<tmp.x<<" "<<tmp.y<<" "<<step<<endl;
}
que[tail++]=tmp;
vis[tmp.x][tmp.y]=true;
}
}
}
}
} bool check(int bat){
memset(dp,-1,sizeof(dp));
int alt=1<<cnt;
dp[1<<fp][fp]=bat;
for(int i=0;i<alt;i++){
for(int j=0;j<cnt;j++){
if(dp[i][j]==-1) continue;
if((i&endfor)==endfor){
if(dp[i][j]!=-1) return true;
}
for(int k=0;k<cnt;k++){
if(dis[node[j].x][node[j].y][node[k].x][node[k].y]==-1) continue;
if(i&(1<<k)) continue;
if(dp[i][j]-dis[node[j].x][node[j].y][node[k].x][node[k].y]<0) continue;
int tmp=dp[i][j]-dis[node[j].x][node[j].y][node[k].x][node[k].y];
if(map[node[k].x][node[k].y]=='G') tmp=bat;
if(tmp>dp[i|(1<<k)][k]) dp[i|(1<<k)][k]=tmp;
}
}
}
return false;
} void slove(){
int l=0,r=1000;
int res=r;
while(l<=r){
int m=(l+r)/2;
if(check(m)){
res=m;
r=m-1;
}
else l=m+1;
}
if(res==1000) printf("-1\n");
else printf("%d\n",res);
} int main(){
while(scanf("%d%d",&n,&m),n||m){
cnt=0;
endfor=0;
for(int i=0;i<n;i++){
scanf("%s",map[i]);
// cout<<map[i]<<endl;
for(int j=0;j<m;j++){
if(map[i][j]=='F'){
fp=cnt;
node[cnt].x=i,node[cnt].y=j;
cnt++;
}
else if(map[i][j]=='G'){
node[cnt].x=i,node[cnt].y=j;
cnt++;
}
else if(map[i][j]=='Y'){
node[cnt].x=i,node[cnt].y=j;
endfor+=(1<<cnt);
cnt++;
}
}
}
memset(dis,-1,sizeof(dis));
for(int i=0;i<cnt;i++){
head=tail=0;
memset(vis,false,sizeof(vis));
bfs(node[i]);
}
slove();
}
return 0;
}

  

HDU 3681的更多相关文章

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

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

  2. hdu 3681 Prison Break

    http://acm.hdu.edu.cn/showproblem.php?pid=3681 题意:一个n*m的矩阵,'F'是起点.机器人从F出发,走到G可以充电,走到Y关掉开关,D不能走进,要求把所 ...

  3. hdu 3681(bfs+二分+状压dp判断)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3681 思路:机器人从出发点出发要求走过所有的Y,因为点很少,所以就能想到经典的TSP问题.首先bfs预 ...

  4. HDU 3681 Prison Break(BFS+二分+状态压缩DP)

    Problem Description Rompire is a robot kingdom and a lot of robots live there peacefully. But one da ...

  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 3681 Prison Break(状态压缩+bfs)

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

  7. HDU 3681 BFS&amp;像缩进DP&amp;二分法

    N*M矩阵.从F出发点.走完全部Y点.每个人格开支1电源点,去G点,电池充满,D无法访问.最小的开始问什么时候满负荷可以去完全部Y.Y和G总共高达15一 第一BFS所有的F.Y.G之间的最短距离. 然 ...

  8. HDU 3681 Prison Break (二分 + bfs + TSP)

    题意:给定上一个 n * m的矩阵,你的出发点是 F,你初始有一个电量,每走一步就会少1,如果遇到G,那么就会加满,每个G只能第一次使用,问你把所有的Y都经过,初始电量最少是多少. 析:首先先预处理每 ...

  9. hdu 3681 压缩dp+搜索

    题意:一个机器人想越狱,他只能带一定电量的电池,'S'表示道路可行,'G'表示充电器, 只可充电一次,但是可以经过很多次.'F'表示起点,'Y'表示要破坏的机关,也是只能破坏一次,但是可以经过无数次. ...

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

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

随机推荐

  1. zookeeper集群安装及使用详解

    1. Zookeeper简介 ZooKeeper是一个开源的分布式框架,提供了协调分布式应用的基本服务.它向外部应用暴露一组通用服务——分布式同步(Distributed Synchronizatio ...

  2. centos语言设置

    . echo $LANG可以查看当前使用的系统语言 . 在终端输入 locale命令,如有zh cn 表示已经安装了中文 . 安装中文语言包yum groupinstall chinese-suppo ...

  3. python自动化测试学习笔记-4内置函数,处理json

    函数.全局变量 写代码时注意的几点事项: 1.一般写代码的时候尽量少用或不用全局变量,首先全局变量不安全,大家协作的情况下,代码公用容易被篡改,其次全局变量会一直占用系统内容. 2.函数里如果有多个r ...

  4. HDU 5306 吉司机线段树

    思路: 后面nlogn的部分是伪证... 大家可以构造数据证明是这是nlog^2n的啊~ 吉老司机翻车了 //By SiriusRen #include <cstdio> #include ...

  5. 研磨JavaScript系列

    JavaScript是一种基于对象和事件驱动并具有相对安全性的客户端脚本语言.同时也是一种广泛用于客户端Web开发的脚本语言,常用来给HTML网页添加动态功能,比如响应用户的各种操作.它最初由网景公司 ...

  6. C#语言最基础的认识变量

    变量是指一块存储数据的内存空间,并且该内存区域的数据内容可以发生变化. 变量是必须先声明后赋值. 基本的语法:数据类型+变量名: 变量名=数据: 简单的使用技巧:声明赋值简写 Static void ...

  7. 阿里云虚拟主机针对恶意频繁攻击式访问造成CPU爆满的解决方法

    最近网站CPU经常爆满,到阿里云提交了工单,工程师给我的处理意见:   您好,虚拟主机CPU占用比较高通常这种情况有两种可能:   一是网站应用程序代码逻辑较复杂,或业务架构效率比较低,在请求了某个网 ...

  8. Java_Web三大框架之Hibernate配置文件(二)

    下面介绍一下编写Hibernate的配置文件,使用Hibernate操作数据库. 开始部署:下载需要的jar包               下载Hibernate           Hibernat ...

  9. ZfNet解卷积:可视化CNN模型( PythonCode可视化Cifar10)

    原文链接:caffe Model的可视化 snapshot: 6000       一个在线可视化小工具:http://blog.csdn.net/10km/article/details/52713 ...

  10. SPPNet论文翻译-空间金字塔池化Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition

    http://www.dengfanxin.cn/?p=403 原文地址 我对物体检测的一篇重要著作SPPNet的论文的主要部分进行了翻译工作.SPPNet的初衷非常明晰,就是希望网络对输入的尺寸更加 ...