题意:

  给出一个最大为16×16的迷宫图和至多3个ghost的起始位置和目标位置,求最少经过几轮移动可以使三个ghost都到达目标位置。每轮移动中,每个ghost可以走一步,也可以原地不动,需要注意的是任意两个ghost不能在相同的位置,也不能出现任意两个ghost对穿。每个迷宫图'#'表示墙,' '表示空地,小写字母表示ghost的起始位置,大写字母表示对应ghost的目标位置。保证任意2×2的空间内都有一个'#'。

分析:

  迷宫图给转换成了图,用邻接表保存起来,这样搜索的时候只走可以走的点。根据任意2×2都有'#'这个细节,可以粗略的估计出整个迷宫中可以走的空地不超过200个,3个ghost的话建一个三维数组vis。num数组记录当前是第几个非#地。g[num][0]记录第num个非#地的上下左右有几个非#地。接下来g[num][1]-g[num][num]代表非#地的序号。

代码:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <queue>
using namespace std;
char map[20][20];
int num[20][20];
int g[200][200];
int vis[200][200][200];
int cnt;
int w,h,n;
int que[10000000][4];
int goal[4];
void bfs()
{
memset(vis,0,sizeof(vis));
int fro=0,rear=1;
vis[que[0][1]][que[0][2]][que[0][3]]=true;
while(fro<rear)
{
int i,j,k,t1,t2,t3;
int &step=que[fro][0],&a=que[fro][1],&b=que[fro][2],&c=que[fro][3];
if(a == goal[1] && b == goal[2] && c == goal[3]) { goal[0] = step; return; }
for(i=0;i<=g[a][0];i++)
{
t1=(i==0?a:g[a][i]);
for(j=0;j<=g[b][0];j++)
{
t2=(j==0?b:g[b][j]);
for(k=0;k<=g[c][0];k++)
{
t3=(k==0?c:g[c][k]);
if((t1&&t2&&t1==t2)||(t1&&t3&&t1==t3)||(t2&&t3&&t2==t3))
continue;
if(t1&&t2&&t1==b&&t2==a)
continue;
if(t1&&t3&&t1==c&&t3==a)
continue;
if(t3&&t2&&t3==b&&t2==c)
continue;
if(!vis[t1][t2][t3])
{
vis[t1][t2][t3]=1;
que[rear][0]=step+1,que[rear][1]=t1,que[rear][2]=t2,que[rear][3]=t3;
++rear;
}
}
}
}
++fro;
}
}
int main()
{
while(scanf("%d%d%d",&w,&h,&n)&&w&&h&&n)
{
int i,j,k;
cnt=0;
gets(map[0]);
for(i=0;i<h;i++)
gets(map[i]);
for(i=0;i<h;i++)
for(j=0;j<w;j++)
if(map[i][j]!='#')
num[i][j]=++cnt;
else
num[i][j]=0;
        memset(g,0,sizeof(g));
for(i=0;i<h;i++)
{
for(j=0;j<w;j++)
{
if(num[i][j])
{
int &pos=num[i][j];
if(num[i+1][j])
g[pos][++g[pos][0]]=num[i+1][j];
if(num[i-1][j])
g[pos][++g[pos][0]]=num[i-1][j];
if(num[i][j+1])
g[pos][++g[pos][0]]=num[i][j+1];
if(num[i][j-1])
g[pos][++g[pos][0]]=num[i][j-1];
}
}
}
que[0][0]=que[0][1]=que[0][2]=que[0][3]=0;
goal[0]=goal[1]=goal[2]=goal[3]=0;
for(i=0;i<h;++i)
{
for(j=0;j<w;++j)
{
if(map[i][j] == 'a')
que[0][1] = num[i][j];
if(map[i][j] == 'b')
que[0][2] = num[i][j];
if(map[i][j] == 'c')
que[0][3] = num[i][j];
}
}
for(i=0;i<h;++i)
{
for(j=0;j<w;++j)
{
if(map[i][j] == 'A')
goal[1] = num[i][j];
if(map[i][j] == 'B')
goal[2] = num[i][j];
if(map[i][j] == 'C')
goal[3] = num[i][j];
}
}
bfs();
printf("%d\n",goal[0]);
}
}

UVA 1601 The Morning after Halloween的更多相关文章

  1. UVA - 1601 The Morning after Halloween (BFS/双向BFS/A*)

    题目链接 挺有意思但是代码巨恶心的一道最短路搜索题. 因为图中的结点太多,应当首先考虑把隐式图转化成显式图,即对地图中可以相互连通的点之间连边,建立一个新图(由于每步不需要每个鬼都移动,所以每个点需要 ...

  2. UVA - 1601 The Morning after Halloween (双向BFS&单向BFS)

    题目: w*h(w,h≤16)网格上有n(n≤3)个小写字母(代表鬼).要求把它们分别移动到对应的大写字母里.每步可以有多个鬼同时移动(均为往上下左右4个方向之一移动),但每步结束之后任何两个鬼不能占 ...

  3. <<操作,&0xff以及|的巧妙运用(以POJ3523---The Morning after Halloween(UVa 1601)为例)

    <<表示左移,如a<<1表示将a的二进制左移一位,加一个0,&0xff表示取最后8个字节,如a&0xff表示取a表示的二进制中最后8个数字组成一个新的二进制数, ...

  4. [uva P1601] The Morning after Halloween

    [uva P1601] The Morning after Halloween 题目链接 非常经典的一道题目,lrj的书上也有(貌似是紫书?). 其实这题看起来就比较麻烦.. 首先要保证小鬼不能相遇, ...

  5. UVa 1601 || POJ 3523 The Morning after Halloween (BFS || 双向BFS && 降维 && 状压)

    题意 :w*h(w,h≤16)网格上有n(n≤3)个小写字母(代表鬼).要求把它们分别移动到对应的大写字母里.每步可以有多个鬼同时移动(均为往上下左右4个方向之一移动),但每步结束之后任何两个鬼不能占 ...

  6. 【UVa】1601 The Morning after Halloween(双向bfs)

    题目 题目     分析 双向bfs,对着书打的,我还调了好久.     代码 #include<cstdio> #include<cstring> #include<c ...

  7. 【Uva 1601】The Morning after Halloween

    [Link]: [Description] 给你一张平面图; 最多可能有3只鬼; 给出这几只鬼的初始位置; 然后,这几只鬼有各自的终点; 每秒钟,这几只鬼能同时移动到相邻的4个格子中的一个 任意两只鬼 ...

  8. UVa 1601 万圣节后的早晨

    https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  9. Uva 1061 The Morning after Halloween

    基本思路是BFS: 1. 题目中已经说了,每相连的2X2格子中必有一个‘#’,也就是,每个点周围最多也就三个方向可以走.因此,可以把所有空格都提出来,形成一个图,直接遍历每条边,而不是每次判断4个方向 ...

随机推荐

  1. GCD 和延时调用

    因为 Playground 不进行特别配置的话是无法在线程中进行调度的,因此本节中的示例代码需要在 Xcode 项目环境中运行.在 Playground 中可能无法得到正确的结果. GCD 是一种非常 ...

  2. c语言中的经典算法

    c语言经典排序以及查找方法 冒泡排序 #include <stdio.h> int main() { int i, j, t, a[11]; /*定义变量及数组为基本整型*/ printf ...

  3. Python 初学

    一. 前言 不怕各位园友笑话,今年年初时,我才知道有一个叫python的编程语言,听说它很大强大,而我只会用c#,正想好好再学一门新语言,还有人分享自己的经验时说,使用python制作的脚本,再做持续 ...

  4. UIView和其子类的几个初始化函数执行的时机

    -(id)initWithFrame:(CGRect)frame - UIView的指定初始化方法; 总是发送给UIView去初始化, 除非是从一个nib文件中加载的; -(id)initWithCo ...

  5. Remove Duplicate Letters

    316. Remove Duplicate Letters Total Accepted: 2367 Total Submissions: 12388 Difficulty: Medium Given ...

  6. C++程序设计实践指导1.9统计与替换字符串中的关键字改写要求实现

    改写要求1:将字符数组str改为字符指针p,动态开辟存储空间 改写要求2:增加统计关键字个数的函数void CountKeyWords() 改写要求3: 增加替换函数void FindKeyWords ...

  7. keepalived+mysql双主复制高可用方案

    MySQL双主复制,即互为Master-Slave(只有一个Master提供写操作),可以实现数据库服务器的热备,但是一个Master宕机后不能实现动态切换.而Keepalived通过虚拟IP,实现了 ...

  8. 【搜索引擎Jediael开发笔记1】搜索引擎初步介绍及网络爬虫

    详细可参考 (1)书箱:<这就是搜索引擎><自己动手写网络爬虫><解密搜索引擎打桩实践> (2)[搜索引擎基础知识1]搜索引擎的技术架构 (3)[搜索引擎基础知识2 ...

  9. Windows 下 Apache HTTP Server 安装、配置以及与 Tomcat 的整合(附图)

    如果您能点开这篇文章,说明您已对熟悉Apache HTTP Server(下文用Apache简称)配置的重要性已很清楚了,本文不在赘述,直接介入正题,请往下阅读: 为便于阅读,列出文章目录: 一.Ap ...

  10. netbeans ide怎么添加yii代码提示

    菜单栏选择工具->选项->php界面里的全局包含路径中选择framework这个文件夹就可以了