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 IFNULL()函数用法MySQL

    用法说明:IFNULL(expr1,expr2) 如果 expr1 不是 NULL,IFNULL() 返回 expr1,否则它返回 expr2. IFNULL()返回一个数字或字符串值,取决于它被使用 ...

  2. ListView列宽自适应,设置ListView.Column[0].Width := -1;

    使用TListView列表显示内容,如果列内容过长,就会显示成‘XXX…’形式,此时如果双击列标题,列宽将变为自适应.用代码设置如下: 1.设置ListView.Column[0].Width := ...

  3. matplotlib--设置线条颜色及形状

    一.控制颜色 b--blue c--cyan(青色) g--green k--black m--magenta(紫红色) r--red w--white y--yellow 颜色有三种表示方法,可以用 ...

  4. JS中“==”和“===”的原理和区别

    1.为什么讨论这个问题? - 有个说法,尽量不用==,而使用===,是这样吗? 2.分析问题,原理是什么? 下面说说ECMAScript 5 language specification里的说明: 1 ...

  5. [转]mac上安装android sdk

    一.先下载android sdk for mac 给二个靠谱的网址: a). http://down.tech.sina.com.cn/page/45703.html b). http://mac.s ...

  6. spring mvc interceptors

    <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/> <mvc:e ...

  7. Jackson基础

    一.所需jar包: jackson-core-x.x.x-rc4.jar.jackson-databind-x.x.x-rc4.jar.jackson-annotations-x.x.x-rc4.ja ...

  8. 解读 Q_D, Q_Q 指针

    见 qglog.h文件定义: #define Q_D(Class) Class##Private * const d = d_func()    #define Q_Q(Class) Class * ...

  9. 如何向GLSL中传入多个纹理

    http://blog.csdn.net/huawenguang/article/details/41245871 如何向GLSL中传入多个纹理 这几天在研究如何实现用GLSL对多个纹理进行融合处理, ...

  10. 2017.11.11 B201 练习题思路及解题方法

    2017.11.11 B201 练习题思路及解题方法 题目类型及涵盖知识点 本次总共有6道题目,都属于MISC分类的题目,涵盖的知识点有 信息隐藏 暴力破解 音轨,摩斯电码 gif修改,base64原 ...