宽搜签到.注意一下传送点的特殊性
比如
#L##
#a#a
#.#.
#P##
不要传送的时候标记两个点了。
//解救小Q
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
int n,m;
char map[51][51];
bool vis[51][51];
struct lx
{
int x,y;
};
lx Q,L;
int xx[]={0,0,1,-1};
int yy[]={1,-1,0,0};
struct cs
{
int x1,y1;
bool flag;
int x2,y2;
}l[27];
int bfs()
{
queue<lx>q;
q.push(L);
lx tmp;
tmp.x=-1,tmp.y=-1;
q.push(tmp);
int ans=0;
while(!q.empty())
{
tmp=q.front();
if(tmp.x==-1&&tmp.y==-1)
{
q.pop();
if(q.empty())return -1;
ans++;
q.push(tmp);continue;
}q.pop();
if(tmp.x==Q.x&&tmp.y==Q.y)return ans;
for(int k=0;k<4;k++)
{
int i=tmp.x+xx[k];
int j=tmp.y+yy[k];
if(i>=n||i<0||j>=m||j<0)continue;
if(!vis[i][j]&&map[i][j]!='#')
{
vis[i][j]=1;
lx now;
now.x=i,now.y=j;
if(map[i][j]>='a'&&map[i][j]<='z')
{
int csi,csj;
if(i==l[map[i][j]-'a'].x1&&j==l[map[i][j]-'a'].y1)
csi=l[map[i][j]-'a'].x2,csj=l[map[i][j]-'a'].y2;
else
csi=l[map[i][j]-'a'].x1,csj=l[map[i][j]-'a'].y1;
now.x=csi,now.y=csj;
}
q.push(now);
}
}
}
return -1;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
char str[51];
scanf("%d%d",&n,&m);
memset(vis,0,sizeof(vis));
memset(l,0,sizeof(l));
for(int i=0;i<n;i++)
{
scanf("%s",str);
for(int j=0;j<m;j++)
{
map[i][j]=str[j];
if(str[j]=='L')L.x=i,L.y=j;
if(str[j]=='Q')Q.x=i,Q.y=j;
if(str[j]>='a'&&str[j]<='z')
{
if(!l[str[j]-'a'].flag)
l[str[j]-'a'].x1=i,l[str[j]-'a'].y1=j,l[str[j]-'a'].flag=1;
else
l[str[j]-'a'].x2=i,l[str[j]-'a'].y2=j;
}
}
}
vis[L.x][L.y]=1;
printf("%d\n",bfs());
}
}