钥匙的数量并不多,状态压缩一下。step[s][x][y]表示走到点(x,y)获得钥匙的状态为s的最少步数。比如状态1001表示得到钥匙D和A。
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
struct Node
{
int s,x,y;
Node(){}
Node(int a,int b,int c)
{s = a; x = b; y = c;}
};
char mp[22][22];
int step[1<<11][21][21],key,n,m,t;
int dir[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};
void init()
{
memset(mp,0,sizeof mp);
memset(step,-1,sizeof step);
}
Node st;
bool inarea(int i,int j)
{
if(i < 1||j < 1||i > n||j > m) return false;
else return true;
}
bool opn(int i,int j,int S)
{
if(mp[i][j] >= 'A'&&mp[i][j] <= 'J')
{
if((1<<(mp[i][j]-'A'))&S) return true;
else return false;
}
else return true;
}
void bfs()
{
queue<Node> Q;
Q.push(st);
step[0][st.x][st.y] = 0;
while(!Q.empty())
{
Node u = Q.front();
//printf("now %d %d stp:%d\n",u.x,u.y,step[u.s][u.x][u.y]);
Q.pop();
if(step[u.s][u.x][u.y] >= t) continue;
if(mp[u.x][u.y] == '^')
{
printf("%d\n",step[u.s][u.x][u.y]);
return;
}
for(int i = 0; i < 4; i++)
{
int tx = u.x+dir[i][0],ty = u.y+dir[i][1],S = u.s;
if(!inarea(tx,ty)||!opn(tx,ty,S)||mp[tx][ty] == '*'||step[S][tx][ty] != -1) continue;
if(mp[tx][ty] >= 'a'&&mp[tx][ty] <= 'j')
S = ((1<<(mp[tx][ty]-'a'))|S);
step[S][tx][ty] = step[u.s][u.x][u.y]+1;
Q.push(Node(S,tx,ty));
}
}
printf("-1\n");
}
int main()
{
while(scanf("%d%d%d",&n,&m,&t) != EOF)
{
init();
for(int i = 1; i <= n; i++)
scanf("%s",mp[i]+1);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
if(mp[i][j] == '@')
{
st.s = 0,st.x = i,st.y = j;
break;
}
bfs();
}
}