一道bfs,主要是难在如何判断是否走的多余。这个时候vis数组需要特殊处理,加个钥匙的状态。如果带着不变的钥匙走了两次,我们就可以以判断方案不行。那么如何判断钥匙的状态呢。一共有10把钥匙,这个时候可以使用2进制。比如,0000000001就代表有第一把钥匙。而1<<10 也就一千多而已。用&运算和|运算很好处理。PS:我的代码vis数组得用bool型,不然mle。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;
const int maxn = 20 + 2;
char G[maxn][maxn];
bool vis[maxn][maxn][1<<10 + 5];
struct node
{
int x, y;
int step, key;
};
int n, m, t;
node door, beg;
int dir[][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
int check(node point)
{
if(point.x >= 0 && point.x < n && point.y >= 0 && point.y < m && point.step < t && G[point.x][point.y] != '*' && !vis[point.x][point.y][point.key]) return true;
return false;
}
int bfs()
{
if(beg.x == door.x && beg.y == door.y && beg.step < t) return 0;
queue<node> q;
q.push(beg);
while(!q.empty())
{
node sq, tq;
sq = q.front();
q.pop();
if(sq.x == door.x && sq.y == door.y && sq.step < t) return sq.step;
for(int i = 0; i < 4; i++)
{
//printf("yes\n");
tq = sq;
tq.step++;
tq.x += dir[i][0];
tq.y += dir[i][1];
if(check(tq))
{
if(G[tq.x][tq.y] >= 'A' && G[tq.x][tq.y] <= 'J')
{
int t = G[tq.x][tq.y] - 'A';
if(tq.key & (1<<t)) {q.push(tq); vis[tq.x][tq.y][tq.key] = 1;}
}
else if(G[tq.x][tq.y] >= 'a' && G[tq.x][tq.y] <= 'j')
{
int t = G[tq.x][tq.y] - 'a';
tq.key = tq.key | (1 << t);
q.push(tq);
vis[tq.x][tq.y][tq.key] = 1;
}
else {q.push(tq); vis[tq.x][tq.y][tq.key] = 1;}
}
}
}
return -1;
}
int main()
{
while(scanf("%d%d%d", &n, &m, &t) == 3)
{
memset(vis, 0, sizeof(vis));
for(int i = 0; i < n; i++)
{
for(int j = 0; j < m; j++)
{
cin>>G[i][j];
if(G[i][j] == '^')
{
door.x = i;
door.y = j;
door.step = 0;
door.key = 0;
}
if(G[i][j] == '@')
{
beg.x = i;
beg.y = j;
beg.key = beg.step = 0;
}
}
}
vis[beg.x][beg.y][0] = 1;
int ans = bfs();
printf("%d\n", ans);
}
return 0;
}