隐式图--UVA - 1601 The Morning after Halloween
2015-10-31 19:22
441 查看
分析:以当前3个小写字母的位置为状态,则问题转化为图的最短路问题。状态总数为256^3,每次转移需要5^3枚举每个小写字母下一步的走法,但是容易超时。由条件“任何一个2×2子网格中至少有一个障碍格”暗示着很多格子都是障碍,并且大部分空地都和障碍相邻,因此不是所有4个方向都能移动,因此可以把所有空格提出来建一个图。这里将原图中的空白点映射为编号,再将三个点的编号合一。预处理可以把每个空白格子的5个方向的下个格子的编号算出来。
#include <cstdio> #include <cctype> #include <cstring> #include <queue> using namespace std; const int maxs = 20; const int maxn = 150; const int dr[] = { -1, 0, 1, 0, 0 }; const int dc[] = { 0, 1, 0, -1, 0 }; int deg[maxn], G[maxn][5]; //deg[i]表示第i个空白格子的方向个数 G[i][j]表示第i个空白格子的第j个方向的格子; int vis[maxn][maxn][maxn]; int n, w, h, s[3], t[3]; //a,b,c是空白格子编号,小于150,在一个字节内 inline int ID(int a, int b, int c) { return (a<<16)|(b<<8)|c; } inline bool conflict(int a, int b, int a2, int b2) { return (a2==b2) || (a==b2 && a2==b); } int bfs() { queue<int> q; memset(vis, -1, sizeof(vis)); q.push(ID(s[0], s[1], s[2])); vis[s[0]][s[1]][s[2]] = 0; while(!q.empty()) { int u = q.front(); q.pop(); int a = (u>>16)&0xff, b = (u>>8)&0xff, c = u&0xff; if(a==t[0] && b==t[1] && c==t[2]) return vis[a][b][c]; for(int i=0; i<deg[a]; i++) { int a2 = G[a][i]; for(int j=0; j<deg[b]; j++) { int b2 = G[b][j]; if(conflict(a, b, a2, b2)) continue; for(int k=0; k<deg[c]; k++) { int c2 = G[c][k]; if(conflict(a, c, a2, c2)) continue; if(conflict(b, c, b2, c2)) continue; if(vis[a2][b2][c2] != -1) continue; vis[a2][b2][c2] = vis[a][b][c] + 1; q.push(ID(a2, b2, c2)); } } } } return -1; } int main() { while(scanf("%d%d%d", &w, &h, &n)&&w) { char maze[20][20]; //cnt空白格子个数 id空白格子到编号的映射 int cnt = 0, x[maxn], y[maxn], id[maxs][maxs]; for(int i=0; i<h; i++) { getchar(); for(int j=0; j<w; j++) { maze[i][j] = getchar(); if(maze[i][j] != '#') { x[cnt] = i; y[cnt] = j; id[i][j] = cnt; if(islower(maze[i][j])) s[maze[i][j]-'a'] = cnt; else if(isupper(maze[i][j])) t[maze[i][j]-'A'] = cnt; cnt++; } } } //给空白格子的每个方向做映射 for(int i=0; i<cnt; i++) { deg[i] = 0; for(int dir=0; dir<5; dir++) { int nx = x[i] + dr[dir], ny = y[i] + dc[dir]; if(maze[nx][ny] != '#') G[i][deg[i]++] = id[nx][ny]; } } if(n <=2 ) { deg[cnt] = 1; G[cnt][0] = cnt; s[2] = t[2] = cnt++; } if(n <=1 ) { deg[cnt] = 1; G[cnt][0] = cnt; s[1] = t[1] = cnt++; } printf("%d\n", bfs()); } return 0; }
相关文章推荐
- Eclipse工程里面:Missing artifact javax.transaction:jta:jar:1.0.1B
- http 事务
- IOS开发涉及有点概念&相关知识点
- codevs 1011 (2001年NOIP全国联赛普及组)
- PHP XDebug Sublime Text 单步调试
- 10个强大的JavaScript库
- html模板
- Android JNI开发流程(android开发艺术探索随笔)
- 上一个博文开源的漫岛APP做了部分优化
- 必须了解的Java 基础题
- Maven: mvn -X 执行报错:No goals have been specified for this build.
- iPhone 6是苹果最畅销机型 市场占有为30%
- 【软工】风险分析
- 希尔排序
- python switch +=*/计算器 和 导入自定义模块 简单操作
- JSON
- OData查询ASP.NET Web API全攻略
- Android IOS WebRTC 音视频开发总结(四九)-- ffmpeg介绍
- Android中的SQLite使用
- python的一些问题以及处理思路