题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1429
题目大意:就是从起点到终点,有路有墙有门有钥匙,钥匙能开对应的门,问能否到达终点,如果能就输出时间,如果不能就输出-1
题解:因为拿到钥匙回到对应门开门可能会走相同的路,所以呢不能单纯的只标记每块地板是否走过,要看该点在该状态(拿了多少钥匙)下是否走过,这里就还是用到了状态压缩,比上一题简单一点,所以写起来也没什么太大问题,嗯。
详解就不说了 去看这个嘛:https://blog.csdn.net/weixin_44049850/article/details/88073715
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <set>
#include <stack>
#include <map>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
int n,m,t;
int sx,sy;
char mp[25][25];
bool vis[25][25][1050];
const int dir[4][2]={
1,0,
-1,0,
0,1,
0,-1
};
struct node{
int x,y,state,s;
node(int a=0,int b=0,int c=0,int d=0):x(a),y(b),state(c),s(d){}
};
bool InMap(int x,int y)
{
return x>=1&&x<=n&&y>=1&&y<=m;
}
int bfs()
{
memset(vis,false,sizeof(vis));
queue<node>q;
q.push(node(sx,sy,0,0));
vis[q.front().x][q.front().y][0]=true;
while(!q.empty())
{
for(int i=0;i<4;i++)
{
int tx=q.front().x+dir[i][0];
int ty=q.front().y+dir[i][1];
if(q.front().s>=t)
return -1;
if(!InMap(tx,ty)||mp[tx][ty]=='*'||vis[tx][ty][q.front().state])
continue;
if(mp[tx][ty]=='^')//走到终点
{
if(q.front().s+1<t)
return q.front().s+1;
return -1;
}
if(mp[tx][ty]>='A'&&mp[tx][ty]<='J')//走到有锁的门
{
if(q.front().state>>(mp[tx][ty]-('A'-'a')-'a')&1)//如果有钥匙
{
q.push(node(tx,ty,q.front().state,q.front().s+1));
vis[tx][ty][q.front().state]=true;
}
else//没有钥匙
continue;
}
else if(mp[tx][ty]>='a'&&mp[tx][ty]<='j')//走到有钥匙的点
{
if(q.front().state>>(mp[tx][ty]-'a')&1)//如果钥匙已经被拿了
{
if(!vis[tx][ty][q.front().state])
{
q.push(node(tx,ty,q.front().state,q.front().s+1));
vis[tx][ty][q.front().state]=true;
}
}
else//钥匙没有被拿,拿上
{
int state=q.front().state|1<<(mp[tx][ty]-'a');
q.push(node(tx,ty,state,q.front().s+1));
vis[tx][ty][state]=true;
}
}
else//普通点
{
if(!vis[tx][ty][q.front().state])
{
q.push(node(tx,ty,q.front().state,q.front().s+1));
vis[tx][ty][q.front().state]=true;
}
}
}
q.pop();
}
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",&mp[i][j]);
if(mp[i][j]=='@')
{
sx=i;
sy=j;
mp[i][j]='.';
}
}
getchar();
}
printf("%d\n",bfs());
}
return 0;
}