UVA 1601 The Morning after Halloween
题意:
给出一个最大为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的更多相关文章
- UVA - 1601 The Morning after Halloween (BFS/双向BFS/A*)
题目链接 挺有意思但是代码巨恶心的一道最短路搜索题. 因为图中的结点太多,应当首先考虑把隐式图转化成显式图,即对地图中可以相互连通的点之间连边,建立一个新图(由于每步不需要每个鬼都移动,所以每个点需要 ...
- UVA - 1601 The Morning after Halloween (双向BFS&单向BFS)
题目: w*h(w,h≤16)网格上有n(n≤3)个小写字母(代表鬼).要求把它们分别移动到对应的大写字母里.每步可以有多个鬼同时移动(均为往上下左右4个方向之一移动),但每步结束之后任何两个鬼不能占 ...
- <<操作,&0xff以及|的巧妙运用(以POJ3523---The Morning after Halloween(UVa 1601)为例)
<<表示左移,如a<<1表示将a的二进制左移一位,加一个0,&0xff表示取最后8个字节,如a&0xff表示取a表示的二进制中最后8个数字组成一个新的二进制数, ...
- [uva P1601] The Morning after Halloween
[uva P1601] The Morning after Halloween 题目链接 非常经典的一道题目,lrj的书上也有(貌似是紫书?). 其实这题看起来就比较麻烦.. 首先要保证小鬼不能相遇, ...
- UVa 1601 || POJ 3523 The Morning after Halloween (BFS || 双向BFS && 降维 && 状压)
题意 :w*h(w,h≤16)网格上有n(n≤3)个小写字母(代表鬼).要求把它们分别移动到对应的大写字母里.每步可以有多个鬼同时移动(均为往上下左右4个方向之一移动),但每步结束之后任何两个鬼不能占 ...
- 【UVa】1601 The Morning after Halloween(双向bfs)
题目 题目 分析 双向bfs,对着书打的,我还调了好久. 代码 #include<cstdio> #include<cstring> #include<c ...
- 【Uva 1601】The Morning after Halloween
[Link]: [Description] 给你一张平面图; 最多可能有3只鬼; 给出这几只鬼的初始位置; 然后,这几只鬼有各自的终点; 每秒钟,这几只鬼能同时移动到相邻的4个格子中的一个 任意两只鬼 ...
- UVa 1601 万圣节后的早晨
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...
- Uva 1061 The Morning after Halloween
基本思路是BFS: 1. 题目中已经说了,每相连的2X2格子中必有一个‘#’,也就是,每个点周围最多也就三个方向可以走.因此,可以把所有空格都提出来,形成一个图,直接遍历每条边,而不是每次判断4个方向 ...
随机推荐
- 单调队列-hdu-3415-Max Sum of Max-K-sub-sequence
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3415 题目大意: 给n个数凑成环状,求某一区间,使得该区间长度不超过k,且总和最大. 解题思路: 区 ...
- GCD 和延时调用
因为 Playground 不进行特别配置的话是无法在线程中进行调度的,因此本节中的示例代码需要在 Xcode 项目环境中运行.在 Playground 中可能无法得到正确的结果. GCD 是一种非常 ...
- ssh整合启动tomcat报java.lang.ClassNotFoundException: org.apache.commons.lang.xwork.StringUtils
今天搭建了一个ssh项目环境,整合后,访问项目首页,登录不进去,控制台报错,后来调试代码后,在获取数据库数据后,返回到action时,又进入了action导致死循环,其实这里是两个问题,控制台报错如下 ...
- 对于IE6及以下版本的处
判断IE6 CSS 通过判断浏览器类型而加载不同的css样式 所有的IE都起作用: <!--[if IE]> <link rel="stylesheet" typ ...
- 《JavaScript 闯关记》之函数
函数是一段代码,它只定义一次,但可以被执行或调用任意次.在 JavaScript 里,函数即对象,程序可以随意操控它们.比如,可以把函数赋值给变量,或者作为参数传递给其他函数,也可以给它们设置属性,甚 ...
- EF查询数据库框架的搭建
一个简单的EF查询框架除了运行项目外,大概需要5个类库项目,当然这个不是一定要这样做,这可以根据自己的需要设置有多少个项目.这里介绍的方法步骤只适合EF零基础的人看看就是了. 在开始之前,先建立一个运 ...
- WCF Rest:不使用UriTemplate使用post方式传参解决HTTP400问题以及参数映射问题
在使用POST方式向服务提交数据时,出现HTTP400异常,以下代码描述: 服务接口定义: [OperationContract] [WebInvoke(ResponseFormat = WebMes ...
- Android SQLite的使用1(非原创)
1.继承SQLiteOpenHelper :public class MyOpenHelper extends SQLiteOpenHelper {} 2.重写下面3个方法 package com.e ...
- union以及一些扩展
select name,age from Students where Age<3unionselect name ,age from Students where Age >4--两个结 ...
- mvc 微软票据验证
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.We ...