UVa 1601 万圣节后的早晨
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 万圣节后的早晨的更多相关文章
- 万圣节后的早晨&&九数码游戏——双向广搜
https://www.luogu.org/problemnew/show/P1778 https://www.luogu.org/problemnew/show/P2578 双向广搜. 有固定起点终 ...
- uva 1601 poj 3523 Morning after holloween 万圣节后的早晨 (经典搜索,双向bfs+预处理优化+状态压缩位运算)
这题数据大容易TLE 优化:预处理, 可以先枚举出5^3的状态然后判断合不合法,但是由于题目说了有很多墙壁,实际上没有那么多要转移的状态那么可以把底图抽出来,然后3个ghost在上面跑到时候就不必判断 ...
- <<操作,&0xff以及|的巧妙运用(以POJ3523---The Morning after Halloween(UVa 1601)为例)
<<表示左移,如a<<1表示将a的二进制左移一位,加一个0,&0xff表示取最后8个字节,如a&0xff表示取a表示的二进制中最后8个数字组成一个新的二进制数, ...
- UVA 1601 The Morning after Halloween
题意: 给出一个最大为16×16的迷宫图和至多3个ghost的起始位置和目标位置,求最少经过几轮移动可以使三个ghost都到达目标位置.每轮移动中,每个ghost可以走一步,也可以原地不动,需要注意的 ...
- 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个方向之一移动),但每步结束之后任何两个鬼不能占 ...
- 【Uva 1601】The Morning after Halloween
[Link]: [Description] 给你一张平面图; 最多可能有3只鬼; 给出这几只鬼的初始位置; 然后,这几只鬼有各自的终点; 每秒钟,这几只鬼能同时移动到相邻的4个格子中的一个 任意两只鬼 ...
- UVa 1601 || POJ 3523 The Morning after Halloween (BFS || 双向BFS && 降维 && 状压)
题意 :w*h(w,h≤16)网格上有n(n≤3)个小写字母(代表鬼).要求把它们分别移动到对应的大写字母里.每步可以有多个鬼同时移动(均为往上下左右4个方向之一移动),但每步结束之后任何两个鬼不能占 ...
- UVA 1601 双向BFS
但是我们还不是很清楚每一次的状态怎么储存?我们可以用一个结构体,将每次的位置存起来,但是这个程序中用了一个更好的储存方法:我们知道最大的格数是16*16个,也就是256个,那么我们转换为二进制表示就是 ...
随机推荐
- js-jquery-对象与JSON字符串互相转换
1:jQuery插件支持的转换方式 代码如下: String→Object$.parseJSON( jsonstr ); //jQuery.parseJSON(jsonstr),可以将json字符串转 ...
- PHP 常用命令行
1.PHP运行指定文件 php -f test.php (-f 可省略) 2.命令行直接运行PHP代码 php -r "phpinfo();" 如果结果太长,还可以 php -r ...
- github多人协同使用。
点击 一:自己跟随别人的项目进行开发 1:首先登陆github,找到自己协同开发的项目. 例如:CrossMountain 的we-pay项目 ,点击 fork,该项目就在自己的账号下面了. 2:在 ...
- 安恒X计划12月月赛
ezweb 主要是序列化问题.没有PHP环境,在线运行的.实例化对象之后修改一下file.然后echo输出序列化的结果.不过下面有一个正则检查.数字前加一个+,影响了正则的匹配,但是对于序列化的还原没 ...
- Thinkpad机器BIOS下清除安全芯片和指纹数据的方法
清除安全芯片: 首先在刚开机出现ThinkPad图标时,按F1进入BIOS界面,然后长按关机按钮关机(注意一定是断电的关机,不是重新启动)然后开机再按F1键进入BIOS设置.选择“Securiy”-〉 ...
- HDU 4500 小Q系列故事——屌丝的逆袭(简单题)
http://acm.hdu.edu.cn/showproblem.php?pid=4500 AC代码: #include<math.h> #include<stdio.h> ...
- CAMediaTiming`协议(9.1 图层时间)
#CAMediaTiming`协议 CAMediaTiming协议定义了在一段动画内用来控制逝去时间的属性的集合,CALayer和CAAnimation都实现了这个协议,所以时间可以被任意基于一个图层 ...
- Python: 合并拼接字符串join()| format() | +
将几个小字符串合并成为一个大的字符串 1如果合并的是一个序列,最快的方式是使用join()方法 >>> parts = ['Is', 'Chicago', 'Not', 'Chica ...
- RPC和RabbitMQ
在单台机器或者单个进程中,如果要调用某个函数,只需要通过函数指针,传入相关参数,即可调用成功并获得结果.但如果是在分布式系统中,某个进程想要调用远程机器上的其它进程提供的方法(服务),就需要采用RPC ...
- 2018-2019-2 20165209 《网络对抗技术》Exp7: 网络欺诈防范
2018-2019-2 20165209 <网络对抗技术>Exp7: 网络欺诈防范 1 基础问题回答和实验内容 1.1基础问题回答 (1)通常在什么场景下容易受到DNS spoof攻击. ...