题目链接:hdu 1242

  这题也是迷宫类搜索,题意说的是 'a' 表示被拯救的人,'r' 表示搜救者(注意可能有多个),'.' 表示道路(耗费一单位时间通过),'#' 表示墙壁,'x' 代表警卫(耗费两个单位时间通过),然后求出 'r' 能找到 'a' 的最短时间,找不到输出 "…………"(竟然在这里也 wa 了一发 -.-||)。很明显是广搜了,因为 'r' 可能有多个,所以我们反过来从 'a' 开始搜,每次搜到 'r' 都更新最小时间值(很重要的一个转换!)。可是这题因为通过 'x' 需要 2 单位时间导致结点间的变化不一致,所以不能用简单的队列(等下会否定这个说法),需要用优先队列,再加上 bfs 就行。

 #include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<algorithm>
using namespace std;
#define For(i,s,t) for(int i=s; i<t; ++i)
const int inf= 0x2fffffff; int n,m;
char s[][];
int dir[][]= {{-,},{,-},{,},{,}}; struct node{
int x,y,t;
node(int x=, int y=, int t= inf): x(x),y(y),t(t) {}
bool operator < (const node &n2) const {
return t > n2.t;
}
}; int main(){
int si,sj;
while(~scanf("%d%d",&n,&m)){
getchar();
For(i,,n+) For(j,,m+) s[i][j]= '#';
for(int i=; i<=n; ++i,getchar())
For(j,,m+) if((s[i][j]= getchar())=='a') si=i, sj= j; int ans= ;
priority_queue<node> q;
q.push(node(si,sj,));
s[si][sj]= '#';
while(q.size()){
node p= q.top(); q.pop();
For(k,,){
int dx= p.x+dir[k][], dy= p.y+dir[k][];
if(s[dx][dy]!='#'){
q.push(node(dx,dy,(s[dx][dy]=='x'? p.t+: p.t+)));
if(s[dx][dy]=='r') ans= min(ans,p.t+);
s[dx][dy]= '#';
}
}
}
if(ans==) puts("Poor ANGEL has to stay in the prison all his life.");
else printf("%d\n",ans);
}
return ;
}

  这一句 " if(s[dx][dy]=='r') ans= min(ans,p.t+1); " 对 'r' 的访问和更新需要很注意位置,一定要放在 " s[dx][dy]= '#'; " 即对已访问结点做标记之前,否则 ans 的值不会变的。

  上面是优先队列+bfs,然后这题实际上还可以用加了特技的普通队列来实现 bfs。怎么做呢,仔细观察这题每两个结点间的(边)权值实际上只有两种:1和2。2对应的就是 'x' 这个结点,只要做特殊处理就行:把它一分为二,分成两个结点 'y' 和 '.' 。大体步骤是:对每个出队的结点访问它的后继结点,当为 'x' 时,把它标记为 'y',和其它结点一样边权值+1入队,如果为 'y',那么就直接跳过,因为 'y' 本来就是从 'x' 转化过来的,并非从它旁边的结点扩展过来;这样的话,每次从队首出对的结点就只有两种可能:'y' 和 '#'(对于 '.' 和 'r' 入队后做的标记),如果是 'y' 的话,就把结点权值+1 再次进队(因为 'x' 本来就耗时 2),然后该结点才真正标记为 '#' 表示确实地访问完,这样的话就能用普通的队列来实现 bfs了,主要就是把那些权值不一致的结点通过拆分成多个等价的结点以转化为权值一致的图。

 #include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<algorithm>
using namespace std;
#define For(i,s,t) for(int i=s; i<t; ++i)
const int inf= 0x2fffffff; int n,m;
char s[][];
int dir[][]= {{-,},{,-},{,},{,}}; struct node{
int x,y,t;
node(int x=, int y=, int t= inf): x(x),y(y),t(t) {}
}; int main(){
int si,sj;
while(~scanf("%d%d",&n,&m)){
getchar();
For(i,,n+) For(j,,m+) s[i][j]= '#';
for(int i=; i<=n; ++i,getchar())
For(j,,m+) if((s[i][j]= getchar())=='a') si=i, sj= j; int ans= ;
queue<node> q;
q.push(node(si,sj,));
s[si][sj]= '#';
while(q.size()){
node p= q.front(); q.pop();
if(s[p.x][p.y]=='y'){
q.push(node(p.x,p.y,p.t+));
s[p.x][p.y]= '#';
continue;
}
For(k,,){
int dx= p.x+dir[k][], dy= p.y+dir[k][];
if(s[dx][dy]=='y') continue;
if(s[dx][dy]!='#'){
q.push(node(dx,dy,p.t+));
if(s[dx][dy]=='x') {
s[dx][dy]= 'y';
continue;
}
if(s[dx][dy]=='r') ans= min(ans,p.t+);
s[dx][dy]= '#';
}
}
}
if(ans==) puts("Poor ANGEL has to stay in the prison all his life.");
else printf("%d\n",ans);
}
return ;
}

  当然,这个如此巧妙的方法是从叉姐那儿听说过来的,我不过尝试着把它实现了而已,只能膜拜那些 OI 大神了 Orz ~~

  另外,很奇怪的是,这题居然也能用 dfs 来做:

 #include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
#define For(i,s,t) for(int i=s; i<t; ++i)
const int maxn= +; char ch[maxn][maxn];
int dir[][]= {{-,,,},{,-,,}};
int Min, num; void dfs(int i, int j, int len)
{
++num;
if(ch[i][j]=='#') return ;
if(ch[i][j]=='x') ++len;
if(len > Min) return ;
if(ch[i][j]=='r'){
Min= min(Min,len);
return ;
}
char c= ch[i][j];
ch[i][j]= '#';
For(k,,) {
int dx= i+dir[][k], dy= j+dir[][k];
dfs(dx,dy,len+);
}
ch[i][j]= c;
} int main()
{
int n,m,si,sj;
while(~scanf("%d%d",&n,&m))
{
getchar();
memset(ch,'#',sizeof(ch));
for(int i=; i<=n; ++i,getchar())
For(j,,m+) if((ch[i][j]= getchar())=='a') si= i, sj=j; Min= ;
dfs(si,sj,);
if(Min==) puts("Poor ANGEL has to stay in the prison all his life.");
else printf("%d\n",Min);
}
return ;
}

  对于这样的题来说 dfs 应该很容易超时才对,可是实际上和 bfs 相差无几,只能再一次吐槽下杭电数据的弱了,anyway,我还是会继续被 HDOJ 虐……

hdu 1242 Rescue的更多相关文章

  1. hdu - 1242 Rescue && hdu - 2425 Hiking Trip (优先队列+bfs)

    http://acm.hdu.edu.cn/showproblem.php?pid=1242 感觉题目没有表述清楚,angel的朋友应该不一定只有一个,那么正解就是a去搜索r,再用普通的bfs就能过了 ...

  2. hdu 1242 Rescue(bfs)

    此刻再看优先队列,不像刚接触时的那般迷茫!这也许就是集训的成果吧! 加油!!!优先队列必须要搞定的! 这道题意很简单!自己定义优先级别! +++++++++++++++++++++++++++++++ ...

  3. 杭电 HDU 1242 Rescue

    http://acm.hdu.edu.cn/showproblem.php?pid=1242 问题:牢房里有墙(#),警卫(x)和道路( . ),天使被关在牢房里位置为a,你的位置在r处,杀死一个警卫 ...

  4. HDU 1242 Rescue(优先队列)

    题目来源: http://acm.hdu.edu.cn/showproblem.php?pid=1242 题目描述: Problem Description   Angel was caught by ...

  5. HDU 1242 Rescue(BFS+优先队列)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1242 题目描述: Problem Description Angel was caught by t ...

  6. HDU 1242 -Rescue (双向BFS)&amp;&amp;( BFS+优先队列)

    题目链接:Rescue 进度落下的太多了,哎╮(╯▽╰)╭,渣渣我总是埋怨进度比别人慢...为什么不试着改变一下捏.... 開始以为是水题,想敲一下练手的,后来发现并非一个简单的搜索题,BFS做肯定出 ...

  7. hdu 1242:Rescue(BFS广搜 + 优先队列)

    Rescue Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other) Total Submis ...

  8. HDU 1242 Rescue (BFS(广度优先搜索))

    Rescue Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submis ...

  9. HDU 1242 Rescue(BFS),ZOJ 1649

    题目链接 ZOJ链接 Problem Description Angel was caught by the MOLIGPY! He was put in prison by Moligpy. The ...

随机推荐

  1. API判断网站IP地址,国家区域

    直接访问http://api.wipmania.com/jsonp 还有经纬度

  2. linux下samba环境搭建

    1.安装samba apt-get install samba samba-common 2.修改配置 /etc/samba/smb.conf 在最后添加以下内容即可实现每个用户访问自己的home目录 ...

  3. 通过PowerShell查询本机IP地址

    脚本内容如下: Write-Host "本机IP地址为:"(ipconfig|findstr "IPv4")[1].split(":")[1 ...

  4. Mac环境下用Java(Sikuli+Robot)实现页游自动化

    转载请注明出自天外归云的博客园:http://www.cnblogs.com/LanTianYou/ Sikulix(以前叫Sikuli)在Mac电脑的环境配置步骤如下: 1.从官网上下载Sikuli ...

  5. 查看centos是多少位的系统命令

    打开命令行 运行下面命令 uname -i 如果是64位系统会显示x86_64 如果显示的是i386则是系统是32位

  6. (6)redis 事务

    redis对事务的支持目前还比较简单.redis只能保证一个client发起的事务中的命令可以连续的执行,而中间不会插入其他client的命令. 由于redis是单线程来处理所有client的请求的所 ...

  7. iis 500 解决方法

    1 打开运行,输入cmd进入到命令提示符窗口. 2 进入到C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727 目录. 3 输入aspnet_regiis.exe ...

  8. 光耦PC817

    光耦一共4个引脚,两个输入,两个输出. 输入接5v和gnd,5v接时加100欧姆电阻.输出不大于35v电压,这时输出端通路(只是通路,不是短路)

  9. <转>“人脉投资”的10条建议

    谁都知道人脉很重要,所以有些人非常勤奋的“做人脉”,他们往往会这样做—— 积极的参与各类线下活动,逢人就换名片.加微信. 见到名人或者重要人物必合影,而且他们还会掏出手机来给你看. 逢年过节,给所有他 ...

  10. ubuntu安装miniconda

    系统:ubuntu15.04   64位 wget -c http://repo.continuum.io/miniconda/Miniconda-latest-Linux-x86_64.sh chm ...