题意:在T-1时间内逃出城堡,途中可能会遇到10种门或钥匙,每种门对应一种钥匙。
简单的BFS,但是判断一个点能否通过不是简单的判断是否走过,而是判断通过该点时拥有的钥匙的状态是否一致。
所以,判重的hash数组要多开一维,表示钥匙的状态。可以用位运算,二进制的10个位分别表示每一种钥匙的状态
View Code
#include<iostream>
#include<algorithm>
#include<queue>
#define M 21
using namespace std;
struct node
{
int x, y, t, state;
node() {}
node(int x, int y, int t, int state): x(x), y(y), t(t), state(state) {}
};
char g[M][M];
bool vis[M][M][1<<10];
int n, m, T;
queue<node> Q;
int dir[4][2] = {{0, 1}, {0, -1}, {1, 0}, { -1, 0}};
int get(char c)
{
return c - (isupper(c) ? 'A' : 'a');
}
int check(int x, int y)
{
if(x < 0 || x >= n || y < 0 || y >= m || g[x][y] == '*')
return true;
return false;
}
int BFS(int si, int sj)
{
node cur;
int t, state;
while(!Q.empty())
Q.pop();
memset(vis, false, sizeof(vis));
vis[si][sj][0] = true;
Q.push(node(si, sj, 0, 0));
while(!Q.empty())
{
cur = Q.front();
Q.pop();
if(cur.t >= T) break;
for(int k = 0; k < 4; k++)
{
int i = cur.x + dir[k][0];
int j = cur.y + dir[k][1];
t = cur.t + 1;
state = cur.state;
if(check(i, j) || vis[i][j][state])
continue;
if(isupper(g[i][j]) && !(state&(1 << get(g[i][j])))) //遇到门,则判断是否拥有对应的钥匙
continue;
if(islower(g[i][j])) //遇到钥匙,则修改一下状态
state |= (1 << get(g[i][j]));
if(g[i][j] == '^') //遇到出口
return t;
if(!vis[i][j][state])
{
vis[i][j][state] = true;//少了这句没发现,MLE无数次
Q.push(node(i, j, t, state));
}
}
}
return -1;
}
int main()
{
int i, j, x, y;
while(scanf("%d%d%d", &n, &m, &T) != EOF)
{
T -= 1;
for(i = 0; i < n; i++)
{
scanf("%s", g[i]);
for(j = 0; j < m; j++)
{
if(g[i][j] == '@')
{
g[i][j] = '.';
x = i, y = j;
}
}
}
printf("%d\n", BFS(x, y));
}
return 0;
}