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

题意:给出w*h的网格,相当于迷宫,有大写字母和小写字母,算出小写字母走到大写字母状态时的最少步数。

思路:建立新图,然后再bfs。

 #include<iostream>
#include<string>
#include<cstring>
#include<queue>
using namespace std; const int maxn = * ; char map[][];
int w, h, n;
int cnt; //非#结点个数
int x[maxn], y[maxn];
int s[], t[]; //记录初末位置
int deg[maxn]; //记录每个格子相连的格子数
int G[maxn][maxn]; //记录每个格子可以走的位置
int new_map[][]; //新图
int d[maxn][maxn][maxn]; //记录步数 int dx[] = { , , -, , };
int dy[] = { , , , , - }; int ID(int x, int y, int z) //二进制压缩存储,方便进出队列
{
return (x << ) | (y << ) | z;
} bool judge(int a, int b, int a2, int b2)
{
return a2 == b2 || (a2 == b && b2 == a);
} void bfs()
{
queue<int> q;
memset(d, -, sizeof(d));
q.push(ID(s[], s[], s[])); //二进制压缩后再进队
d[s[]][s[]][s[]] = ;
while (!q.empty())
{
int u = q.front();
q.pop();
int a = (u >> ) & 0xff; //得到压缩前的数据
int b = (u >> ) & 0xff;
int c = u & 0xff;
if (a==t[] && b==t[] && c==t[]) //得到目标状态
{
cout << d[a][b][c] << endl;
return;
}
for (int i = ; i < deg[a]; i++)
{
int a2 = G[a][i];
for (int j = ; j < deg[b]; j++)
{
int b2 = G[b][j];
if (judge(a, b, a2, b2)) continue; //删去不符合条件的走法
for (int k = ; k < deg[c]; k++)
{
int c2 = G[c][k];
if (judge(a, c, a2, c2)) continue;
if (judge(b, c, b2, c2)) continue;
if (d[a2][b2][c2] != -) continue;
d[a2][b2][c2] = d[a][b][c] + ;
q.push(ID(a2, b2, c2));
}
}
}
}
} int main()
{
//freopen("D:\\txt.txt", "r", stdin);
while (cin>>w>>h>>n && n)
{
getchar();
cnt = ; //记录非#结点个数
memset(map, , sizeof(map));
memset(deg, , sizeof(deg));
for (int i = ; i < h; i++)
{
fgets(map[i], , stdin);
for (int j = ; j < w; j++)
{
if (map[i][j] != '#')
{
x[cnt] = i;
y[cnt] = j;
new_map[i][j] = cnt; //建图记录结点
if (map[i][j] >= 'a' && map[i][j] <= 'c') s[map[i][j] - 'a'] = cnt;
if (map[i][j] >= 'A' && map[i][j] <= 'C') t[map[i][j] - 'A'] = cnt;
cnt++;
}
}
} for (int i = ; i < cnt; i++)
{
for (int k = ; k < ; k++)
{
int xx = x[i] + dx[k];
int yy = y[i] + dy[k];
if (map[xx][yy] != '#') G[i][deg[i]++] = new_map[xx][yy]; //如果可以走,则将第i个点的第deg[i]个方向的下一个格子记录
}
} //如果不满三个鬼,强行添加结点使之构成三个结点 if (n <= ) //添加虚拟结点
{
deg[cnt] = ; G[cnt][] = cnt; s[] = t[] = cnt++;
}
if (n <= )
{
deg[cnt] = ; G[cnt][] = cnt; s[] = t[] = cnt++;
} bfs();
}
return ;
}

UVa 1601 万圣节后的早晨的更多相关文章

  1. 万圣节后的早晨&&九数码游戏——双向广搜

    https://www.luogu.org/problemnew/show/P1778 https://www.luogu.org/problemnew/show/P2578 双向广搜. 有固定起点终 ...

  2. uva 1601 poj 3523 Morning after holloween 万圣节后的早晨 (经典搜索,双向bfs+预处理优化+状态压缩位运算)

    这题数据大容易TLE 优化:预处理, 可以先枚举出5^3的状态然后判断合不合法,但是由于题目说了有很多墙壁,实际上没有那么多要转移的状态那么可以把底图抽出来,然后3个ghost在上面跑到时候就不必判断 ...

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

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

  4. UVA 1601 The Morning after Halloween

    题意: 给出一个最大为16×16的迷宫图和至多3个ghost的起始位置和目标位置,求最少经过几轮移动可以使三个ghost都到达目标位置.每轮移动中,每个ghost可以走一步,也可以原地不动,需要注意的 ...

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

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

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

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

  7. 【Uva 1601】The Morning after Halloween

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

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

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

  9. UVA 1601 双向BFS

    但是我们还不是很清楚每一次的状态怎么储存?我们可以用一个结构体,将每次的位置存起来,但是这个程序中用了一个更好的储存方法:我们知道最大的格数是16*16个,也就是256个,那么我们转换为二进制表示就是 ...

随机推荐

  1. 让人抓狂的MySQL安装-8.0.12版本

    今天一个下午就做了一件事,把MySQL安装成功,安装的过程让人很狂躁.于是一边骂,一边查错,才把这个软件给安装成功了. 详细的安装步骤,这里就不赘述了.参见https://blog.csdn.net/ ...

  2. Spark On Yarn Cluster生产环境下JVM的OOM和Stack Overflow问题

    1.Spark on Yarn下JVM的OOM问题及解决方式 2.Spark中Driver的Stack Overflow的问题及解决方式 Spark on Yarn cluster mode: 此时有 ...

  3. [dt]世纪历史长河年代表

    年代口诀 夏商与西周, 东周分两段, 春秋和战国, 一统秦两汉, 三分魏蜀吴, 二晋前后延, 南北朝并列, 隋唐五代传, 宋元明清后, 皇朝至此完. 中国历史长河年代表 参考: 中国历史朝代顺序表.年 ...

  4. RNN实现字符级语言模型 - 恐龙岛(自己写RNN前向后向版本+keras版本)

    问题描述:样本为所有恐龙名字,为了构建字符级语言模型来生成新的名称,你的模型将学习不同的名称模式,并随机生成新的名字. 在这里你将学习到: 如何存储文本数据以便使用rnn进行处理. 如何合成数据,通过 ...

  5. Android开发中,系统是如何区分不同的App的(转自csdn)

    转自:http://bbs.csdn.net/topics/391868975?page=1 1判断是否为同一个app,仅仅是包名,签名是保证你的app不被第三方恶意替换.当包名相同,但签名不同时,系 ...

  6. SSM三层模型之间的参数传递

    Controller接收各种形式的传参:   RequestMapping()包含三部分信息:   表单传参: 1.表单action请求   1:参数名称和顺序都要和表单字段名称一致,直接接收(适合字 ...

  7. 2:2 strus2的配置文件

    strus2 的xml配置文件主要负责Action的管理,常放在WEB-INF/classes目录下,被自动加载 在strus-core jar包下找dtd文件,里面有xml的头信息.也有contan ...

  8. VS2010/MFC编程入门之三十一(常用控件:树形控件Tree Control 下)

    前面一节讲了树形控件Tree Control的简介.通知消息以及相关数据结构,本节继续讲下半部分,包括树形控件的创建.CTreeCtrl类的主要成员函数和应用实例. 树形控件的创建 MFC为树形控件提 ...

  9. 20154312 曾林 Exp4恶意软件分析

    写在前面 如果把恶意软件比作罪犯的话,怎么看这次实验? 实验目的:以后能够在茫茫人海中找到罪犯. 实验过程:现在以及抓到了一个罪犯,把他放到茫茫人海里去,看看他和普通人有啥区别.这些区别就是罪犯的特征 ...

  10. Java应用开发的一条重要经验:先建立基础设施

    一旦为应用建立良好的基础设施, 后续的开发就会变得容易而快速.这些基础设施包括: 1.    线程池的建立与配置: 在 JDK 并发库的基础上建立适合于应用的多任务接口和框架: 2.   外部系统服务 ...