原题:http://acm.hdu.edu.cn/showproblem.php?pid=1885
题意:问从*到X至少走几步;
’ # ‘ 是墙,’ . ‘ 是空地;大写字母是门,小写字母是钥匙,字母相同才可配对,如 b 开 B ,且钥匙一直都在并非开完一扇门钥匙就失效了;
思路:手里拥有钥匙的状态,状压一下,每次走到一个点,判断在已拥有的钥匙的状态下这个点是否走过 vis[i][j][status];
#include<cstdio>
#include<cstring>
#include<string>
#include<queue>
using namespace std;
const int maxn = 110;
char map[maxn][maxn];
bool vis[maxn][maxn][35];
int n, m;
int sx, sy;
int f[4][2] = {-1, 0, 0, -1, 0, 1, 1, 0};
struct node
{
int x, y;
int step;
int key;
};
int Num(char c)
{
if(c == 'B' || c == 'b') return 1;
if(c == 'G' || c == 'g') return 2;
if(c == 'R' || c == 'r') return 3;
if(c == 'Y' || c == 'y') return 4;
}
void bfs()
{
queue<node>q;
while(!q.empty()) q.pop();
node a;
a.x = sx, a.y = sy;
a.step = 0;
a.key = 0;
vis[sx][sy][0] = true;
q.push(a);
while(!q.empty())
{
node b = q.front();
q.pop();
if(map[b.x][b.y] == 'X')
{
printf("Escape possible in %d steps.\n", b.step);
return;
}
for(int i = 0;i<4;i++)
{
node c;
int nx = b.x + f[i][0];
int ny = b.y + f[i][1];
int key = b.key;
if(nx < 0 || ny < 0 || nx >= n || ny >= m || map[nx][ny] == '#') continue;
if(map[nx][ny] >= 'A' && map[nx][ny] <= 'Z' && !vis[nx][ny][key] && map[nx][ny] != 'X')
{
int k = Num(map[nx][ny]);
if(key & (1 << k))
{
vis[nx][ny][key] = true;
c.x = nx, c.y = ny, c.key = b.key, c.step = b.step + 1;
q.push(c);
}
}
else if(map[nx][ny] >= 'a' && map[nx][ny] <= 'z')
{
int k = Num(map[nx][ny]);
key = key | (1 << k);
if(!vis[nx][ny][key])
{
vis[nx][ny][key] = true;
c.x = nx, c.y = ny, c.key = key, c.step = b.step + 1;
q.push(c);
}
}
else
{
if(!vis[nx][ny][key])
{
vis[nx][ny][key] = true;
c.x = nx, c.y = ny, c.key = b.key, c.step = b.step + 1;
q.push(c);
}
}
}
}
printf("The poor student is trapped!\n");
return;
}
int main()
{
while(~scanf("%d%d", &n, &m))
{
if(n == 0 && m == 0) break;
for(int i = 0;i<n;i++)
{
scanf("%s", map[i]);
for(int j = 0;j<m;j++)
{
if(map[i][j] == '*')
sx = i, sy = j;
}
}
memset(vis, false, sizeof vis);
bfs();
}
return 0;
}