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. InnoSQL/MySQL并行复制的实现与配置

    InnoSQL/MySQL并行复制的实现与配置 http://www.innomysql.net/article/6276.html 并行复制之前的解决方案 InnoSQL在5.5.30-v4版本中支 ...

  2. Prometheus+Grafana+Altermanager搭建监控系统

    基本概念 Prometheus 时间序列化数据库,我的理解就是将数据打上标签,以时间维度存储.后面有机会在深入研究. Prometheus架构如下: Grafana Prometheus中存储的数据, ...

  3. HashMap(不是线程安全)与ConcurrentHashMap(线程安全)

    HashMap不是线程安全的 ConcurrentHashMap是线程安全的 从JDK1.2起,就有了HashMap,正如前一篇文章所说,HashMap不是线程安全的,因此多线程操作时需要格外小心. ...

  4. 原生的强大DOM选择器querySelector - querySelector和querySelectorAll

    在传统的 JavaScript 开发中,查找 DOM 往往是开发人员遇到的第一个头疼的问题,原生的 JavaScript 所提供的 DOM 选择方法并不多,仅仅局限于通过 tag, name, id ...

  5. 非受限联合体 - 现代C++新特性总结

    非受限联合体 非受限联合体:C++98中并不是所有数据类型都能够成为union的数据成员,不允许联合体拥有非POD(Plain Old Data).静态或引用类型的成员. C++11中取消了联合体对于 ...

  6. PAT 1072 Gas Station[图论][难]

    1072 Gas Station (30)(30 分) A gas station has to be built at such a location that the minimum distan ...

  7. Leetcode: Merge k Sorted List

    Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. 参 ...

  8. SQL查询遍历数据方法一 [ 临时表 + While循环]

    以下以SQL Server 2000中的NorthWind数据库中的Customers表为例, 用 临时表 + While循环 的方法, 对Customers表中的CompanyName列进行遍历 c ...

  9. CodeForces - 946D Timetable (分组背包+思维)

    题意 n天的课程,每天有m个时间单位.若时间i和j都有课,那么要在学校待\(j-i+1\)个时间.现在最多能翘k节课,问最少能在学校待多少时间. 分析 将一天的内容视作一个背包的组,可以预处理出该天内 ...

  10. cf 459E

    cf459E 这题说的是 给定一个n点m条边的带边权的有向图,从中找出一条路径(可以带环),该路径包含的边数最多,并且要求路径中的权值必须严格递增,然后对边进行排序完个后采用dp去解特殊判断一下边权值 ...