题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1429
代码如下。
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
#include <stack>
#include <string>
#include <cstring>
#include <cassert>
using namespace std;
typedef long long ll;
const int maxn=55555;
const int INF=0x7fffffff;
const int mod=1e7+7;
#define LSON l, m, rt<<1
#define RSON m+1, r, rt<<1|1
#define ESP 1e-7
struct point {
int x, y, keys;
}Start, End;
char _map[22][22];
int vis[22][22][1111];//记录到点(i, j)有k个钥匙的步数。k用二进制进行压缩,总共最多十把钥匙,所以数组开过1024即可。
int xx[4]= {1, 0, -1, 0};
int yy[4]= {0, 1, 0, -1};
int n, m, t;
int BFS(point s, point e) {
memset(vis, 0, sizeof(vis));
queue<point> q;
q.push(s);
vis[s.x][s.y][s.keys]=1;
while(!q.empty()) {
point ff=q.front();
q.pop();
if(vis[ff.x][ff.y][ff.keys]-1>=t)//如果超过时间,去掉
continue;
if(ff.x==e.x && ff.y==e.y)//到达终点结束
return vis[ff.x][ff.y][ff.keys]-1;//因为起点的步数当为1
for(int i=0;i<4;i++) {
point pi;
int xi=pi.x=ff.x+xx[i];
int yi=pi.y=ff.y+yy[i];
pi.keys=ff.keys;
if(xi>=1 && xi<=n && yi>=1 && yi<=m && _map[xi][yi]!='*' && !vis[xi][yi][pi.keys]) {
if(_map[xi][yi]>='a' && _map[xi][yi]<='j') {
int key=1<<(_map[xi][yi]-'a');
pi.keys=ff.keys|key;//添加钥匙
vis[xi][yi][pi.keys]=vis[ff.x][ff.y][ff.keys]+1;
q.push(pi);
}
else if(_map[xi][yi]=='.') {
vis[xi][yi][pi.keys]=vis[ff.x][ff.y][ff.keys]+1;
q.push(pi);
}
else {
int lock=1<<(_map[xi][yi]-'A');
if(lock&ff.keys) {//判断是否有该把钥匙
vis[xi][yi][pi.keys]=vis[ff.x][ff.y][ff.keys]+1;
q.push(pi);
}
}
}
}
}
return -1;
}
int main() {
while(~scanf("%d%d%d", &n, &m, &t)) {
getchar();
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++) {
scanf("%c", &_map[i][j]);
if(_map[i][j]=='@') {
Start.x=i;
Start.y=j;
Start.keys=0;
_map[i][j]='.';
}
else if(_map[i][j]=='^') {
End.x=i;
End.y=j;
End.keys=0;
_map[i][j]='.';
}
}
getchar();
}
printf("%d\n", BFS(Start, End));
}
return 0;
}