例题7-9 万圣节后的早晨 UVa1601
来源:互联网 发布:泽野螳螂 知乎 编辑:程序博客网 时间:2024/05/20 06:30
【题目链接】点击打开链接
【题意】w*h(w,h <= 16)网格中有n(n<=3)个小写字母(代表鬼),要求把它们分别移动到对应的大写字母里。每一步可以有多个鬼移动(均为往上下左右4个方向之1移动),但每一步结束之后,任何两个鬼不能占用同一个位置,也不能在一步之内交换位置。
【解题方法】方法是把所有可以移动的格子找出来建立一张图,就是把障碍物给删除,统计每个可以空格或者有鬼的格子可以移动到哪些格子,这样在判断的时候就节省了许多时间。然后bfs找最短路。具体可以看紫书206页,书上还提到了可以用双向BFS的方法,现在不会。
【AC代码】
////Created by BLUEBUFF 2016/1/9//Copyright (c) 2016 BLUEBUFF.All Rights Reserved//#pragma comment(linker,"/STACK:102400000,102400000")#include <ext/pb_ds/assoc_container.hpp>#include <ext/pb_ds/tree_policy.hpp>#include <ext/pb_ds/hash_policy.hpp>#include <set>#include <map>#include <queue>#include <stack>#include <cmath>#include <cstdio>#include <time.h>#include <cstdlib>#include <cstring>#include <complex>#include <sstream> //isstringstream#include <iostream>#include <algorithm>using namespace std;//using namespace __gnu_pbds;typedef long long LL;typedef pair<int, LL> pp;#define REP1(i, a, b) for(int i = a; i < b; i++)#define REP2(i, a, b) for(int i = a; i <= b; i++)#define REP3(i, a, b) for(int i = a; i >= b; i--)#define CLR(a, b) memset(a, b, sizeof(a))#define MP(x, y) make_pair(x,y)template <class T1, class T2>inline void getmax(T1 &a, T2 b) { if (b>a)a = b; }template <class T1, class T2>inline void getmin(T1 &a, T2 b) { if (b<a)a = b; }const int maxn = 20;const int maxm = 300;const int maxs = 10;const int maxp = 1e3 + 10;const int INF = 1e9;const int UNF = -1e9;const int mod = 1e9 + 7;const double PI = acos(-1);//headint getnum(int a, int b, int c){ //编码 return (a << 16) | (b << 8) | c;}int ok(int a, int b, int a1, int b1){ //两种非法的情况 return ((a1 == b1) || (a1 == b && b1 == a));}int dir[5][2] = {{0, 1}, {0, -1}, {-1, 0}, {1, 0}, {0, 0}};int id[maxn][maxn], G[maxm][5]; //由于相邻节点最多5个,包含自身int st[3], en[3]; //st存放起始位置,en存放结束位置int edge[maxm], d[maxm][maxm][maxm];//edge数组存放第i个结点具有的相邻结点数目int w, h, n, cnt;char M[maxn][maxn]; //原地图void bfs(){ queue <int> q; memset(d, -1, sizeof(d)); q.push(getnum(st[0], st[1], st[2])); d[st[0]][st[1]][st[2]] = 0; while(!q.empty()) { int u = q.front(); q.pop(); int a = (u >> 16) & 255, b = (u >> 8) & 255, c = u & 255; //解码各个鬼的位置 if(a == en[0] && b == en[1] && c == en[2]) return; //找个目标状态 for(int i = 1; i <= edge[a]; i++){ int a1 = G[a][i]; for(int j = 1; j <= edge[b]; j++){ int b1 = G[b][j]; if(ok(a, b, a1, b1)) continue; for(int k = 1; k <= edge[c]; k++){ int c1 = G[c][k]; if(ok(a, c, a1, c1)) continue; if(ok(b, c, b1, c1)) continue; if(d[a1][b1][c1] == -1){ d[a1][b1][c1] = d[a][b][c] + 1; q.push(getnum(a1, b1, c1)); } } } } }}int main(){ while(scanf("%d%d%d", &w, &h, &n) != EOF && n) { char c = getchar(); while(c != '\n') c = getchar(); REP2(i, 1, h){ fgets(M[i] + 1, 20, stdin); } cnt = 0; int x[maxm], y[maxm]; REP2(i, 1, h){ REP2(j, 1, w){ if(M[i][j] != '#'){ id[i][j] = ++cnt;//利用矩阵存稀疏图,cnt是每个结点的序号,也代表了最终的结点数 x[cnt] = i; y[cnt] = j; if('a' <= M[i][j] && M[i][j] <= 'c'){ st[M[i][j] - 'a'] = cnt; //找每一个鬼 } if('A' <= M[i][j] && M[i][j] <= 'C'){ en[M[i][j] - 'A'] = cnt; //找目标位置 } } } } REP2(i, 1, cnt){ edge[i] = 0; REP1(j, 0, 5){ int dx = x[i] + dir[j][0]; int dy = y[i] + dir[j][1]; if(M[dx][dy] != '#'){ G[i][++edge[i]] = id[dx][dy];//寻找每个结点的相邻结点,包括自己 } } } if(n <= 2){ edge[++cnt] = 1; G[cnt][1] = cnt; st[2] = en[2] = cnt; } if(n <= 1){ edge[++cnt] = 1; G[cnt][1] = cnt; st[1] = en[1] = cnt; } bfs(); printf("%d\n", d[en[0]][en[1]][en[2]]); } return 0;}
0 0
- 例题7-9 万圣节后的早晨 UVa1601
- 例题7-9 万圣节后的早晨 UVa1601
- 例题7-9 万圣节后的早晨(The Morning after Halloween, Japan 2007, UVa1601)
- UVa1601万圣节后的早晨
- UVa 1601 例题7-9 万圣节后的早晨
- UVa1601 万圣节后的早晨(The Morning after Halloween)
- UVa524 例题7-9 万圣节后的早晨 (单向+双向)BFS
- 万圣节后的早晨
- uva 1601 万圣节后的早晨 —— bfs
- uva 1601万圣节后的早晨 双向bfs
- 万圣节的第二天早晨
- Uva1601 The Morning after Halloween【隐式图bfs+图重建】【例题7-9】
- uva 1601(万圣节的早晨,经典搜索)
- uva 1601 poj 3523 Morning after holloween 万圣节后的早晨 (经典搜索,双向bfs+预处理优化+状态压缩位运算)
- uva1601题解,pascal留守儿童的血泪
- 万圣节前夜的系统升级
- 万圣节的“荒唐收购”
- 最后的一个万圣节
- Android第十一课;相对布局
- JavaServer Faces 2.0 requires Dynamic Web Module 2.5 or newer..Maven Java EE Configuration
- 2017.1.9--linux下的C语言--目录与文件
- 微信小程序开发前奏
- 人工智能-未来
- 例题7-9 万圣节后的早晨 UVa1601
- Python的hasattr() getattr() setattr() 函数使用方法详解
- 算法与设计分析作业3(贪心)
- 如何命令行下运行脚本及传递参数
- 微信的模拟登录
- win10开机卡在加载界面问题的解决办法
- 机器学习笔记——最小二乘法
- LayoutAnimation/LayoutTransition源码分析
- C++11 lambda