http://acm.hdu.edu.cn/showproblem.php?pid=3085

出的很好的双向bfs,卡时间,普通的bfs会超时

题意方面:

1. 可停留

2. ghost无视墙壁

3. 需要检查两次某个地点是否有ghost,正要到达的时候(t),以及即将启程的时候(t+1).

在编程时需要注意的是:

当两个人汇合时,不需要检查即将启程的那次.

M可以走3步,在这3步中间只需要检查是否能到达(t)

出问题在: 1. 检查时间处理的不清晰

2.普通bfs会超时

3.双向bfs需要完全处理完某一时间,否则会出现

  a.女孩已经走完了程序自动退出(que[0].empty()&&!que[1].empty())

  b.因为女孩的步数比较多不是最优解的情况

#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;
const int inf =0x3fffffff;
const int maxn=1e3+3;
char maz[maxn][maxn];
int n,m;
struct pnt
{
int x,y;
pnt()
{
x=y=0;
}
pnt(int tx,int ty):x(tx),y(ty) {}
} z[2],b,g;
typedef pair<pnt,int> P;
int zn; bool ok(int x,int y,int time)
{
for(int i=0; i<2; i++)
{
int h=abs(x-z[i].x)+abs(y-z[i].y);
if(h<=2*time)
{
return false;
}
}
return true;
} int dg[maxn][maxn],db[maxn][maxn];
queue<pnt> que[2];
const int dx[4]= {1,-1,0,0};
const int dy[4]= {0,0,1,-1};
bool in(int x,int y)
{
return x>=0&&x<n&&y>=0&&y<m&&maz[x][y]!='X';
}
int tempt(int step,int s,int cnt)
{
int sz=que[s].size();
while(sz--)
{
pnt f=que[s].front();que[s].pop();
if(!ok(f.x,f.y,step))continue;
for(int di=0; di<4; di++)
{
pnt t=pnt(f.x+dx[di],f.y+dy[di]);
if(in(t.x,t.y)&&ok(t.x,t.y,step))
{
if(s)
{
if(db[t.x][t.y]>step)
{
db[t.x][t.y]=step;
if(dg[t.x][t.y]!=inf)
return step;
que[s].push(t);
}
}
else
{
if(dg[t.x][t.y]>step)
{
dg[t.x][t.y]=step;
if(db[t.x][t.y]!=inf)
return step;
que[s].push(t);
}
}
}
}
}
return -1;
} int bfs()
{
while(!que[0].empty())que[0].pop();
while(!que[1].empty())que[1].pop(); que[0].push(g);
que[1].push(b);
int step=0;
while(!que[0].empty()&&!que[1].empty())
{
step++;
int tmp;
if((tmp=tempt(step,0,0))!=-1)return tmp;
if((tmp=tempt(step,1,1))!=-1)return tmp;
if((tmp=tempt(step,1,2))!=-1)return tmp;
if((tmp=tempt(step,1,3))!=-1)return tmp;
}
return -1;
} void init()
{
zn=0;
for(int i=0; i<n; i++)fill(dg[i],dg[i]+m,inf);
for(int i=0; i<n; i++)fill(db[i],db[i]+m,inf);
}
int main()
{
int T;
scanf("%d",&T);
for(int ti=1; ti<=T; ti++)
{
scanf("%d%d",&n,&m);
init();
for(int i=0; i<n; i++)
{
scanf("%s",maz[i]);
for(int j=0; j<m; j++)
{
if(maz[i][j]=='Z')
{
z[zn++]=pnt(i,j);
}
else if(maz[i][j]=='G')
{
g=pnt(i,j);
dg[g.x][g.y]=0;
}
else if(maz[i][j]=='M')
{
b=pnt(i,j);
db[b.x][b.y]=0;
}
}
}
int ans=bfs();
printf("%d\n",ans);
}
return 0;
}

HDU 3085 Nightmare II 双向bfs 难度:2的更多相关文章

  1. HDU 3085 Nightmare Ⅱ(双向BFS)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3085 题目大意:给你一张n*m地图上,上面有有 ‘. ’:路 ‘X':墙 ’Z':鬼,每秒移动2步,可 ...

  2. HDOJ3085 Nightmare II 双向BFS

    重构一遍就A了...但这样效率太低了...莫非都要重构???QWQ 每一秒男同志bfs3层,女同志bfs1层.注意扩展状态时,要判一下合不合法再扩展,而不是只判扩展的状态合不合法,否则有可能由非法的走 ...

  3. HDU 3085 Nightmare Ⅱ(噩梦 Ⅱ)

    HDU 3085 Nightmare Ⅱ(噩梦 Ⅱ) Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Ja ...

  4. HDU - 3085 Nightmare Ⅱ

    HDU - 3085 Nightmare Ⅱ 双向BFS,建立两个队列,让男孩女孩一起走 鬼的位置用曼哈顿距离判断一下,如果该位置与鬼的曼哈顿距离小于等于当前轮数的两倍,则已经被鬼覆盖 #includ ...

  5. HDU 3085 Nightmare Ⅱ (双向BFS)

    Nightmare Ⅱ Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tota ...

  6. HDU 3085 Nightmare Ⅱ 双向BFS

    题意:很好理解,然后注意几点,男的可以一秒走三步,也就是三步以内的都可以,鬼可以穿墙,但是人不可以,鬼是一次走两步 分析:我刚开始男女,鬼BFS三遍,然后最后处理答案,严重超时,然后上网看题解,发现是 ...

  7. HDU 1043 Eight(双向BFS+康托展开)

    http://acm.hdu.edu.cn/showproblem.php?pid=1043 题意:给出一个八数码,求出到达指定状态的路径. 思路:路径寻找问题.在这道题里用到的知识点挺多的.第一次用 ...

  8. Nightmare Ⅱ(双向BFS)

    Problem Description Last night, little erriyue had a horrible nightmare. He dreamed that he and his ...

  9. HDU 6171 Admiral(双向BFS+队列)题解

    思路: 最大步骤有20,直接BFS会超时. 因为知道开始情况和结果所以可以用双向BFS,每个BFS规定最大步骤为10,这样相加肯定小于20.这里要保存每个状态搜索到的最小步骤,用Hash储存.当发现现 ...

随机推荐

  1. [转载] DevOps年中盘点:国外最受欢迎的10篇技术文章

    本文根据高效运维系列微信群的群友投稿整理而成.“高效运维”公众号作为本系列群的官方唯一公众号,原创并独家首发. 欢迎关注“高效运维”公众号,以免费参加「运维讲坛」每月一次的线下交流活动:并抢先赏阅干货 ...

  2. elastic

    学习链接 http://rfyiamcool.blog.51cto.com/1030776/1420811?utm_source=tuicool&utm_medium=referral

  3. 关于css3的自定义字体

    css3的@font-face属性打破了中文页面字体一成不变的格局,但今天本菜在用的时候并不那么爽.开始各种引用外部ttf文件失败.下了300M+的字体文件,苦逼的试了一下午.终于有一个ttf引用成功 ...

  4. 抓取oschina上面的代码分享python块区下的 标题和对应URL

    # -*- coding=utf-8 -*- import requests,re from lxml import etree import sys reload(sys) sys.setdefau ...

  5. Oracle 逐条和批量插入数据方式对比

    创建测试表 create table base_users ( userid         varchar2(16), username  varchar2(32), passwd      var ...

  6. GFS Google File System(中文翻译)

    Google文件系统 GFS是一个可扩展的分布式文件系统,用于大型的.分布式的.对大量数据进行访问的应用.它运行于廉价的普通硬件上,但可以提供容错功能.它可以给大量的用户提供总体性能较高的服务. 1. ...

  7. (四)Ubuntu 14.04 文件服务器--samba的安装和配置

    samba是Linux系统上的一种文件共享协议,可以实现Windows系统访问Linux系统上的共享资源,现在介绍一下如何在Ubuntu 14.04上安装和配置samba一. 一.更新源列表 打开&q ...

  8. ttttttttttt

    http://www.2cto.com/kf/201606/519504.html http://a67474506.iteye.com/blog/2079590 spring boot: http: ...

  9. [转]Oracle中INITRANS和MAXTRANS参数

    每个块都有一个块首部.这个块首部中有一个事务表.事务表中会建立一些条目来描述哪些事务将块上的哪些行/元素锁定.这个事务表的初始大小由对象的INITRANS 设置指定.对于表,这个值默认为2(索引的IN ...

  10. 转!!java反射机制

    Java 反射机制 基本概念 在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法? 答案是肯定的. 这种动态获取类的信息以及动态调用对象 ...