您的位置:首页 > 其它

隐式图--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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: