这道题的解法非常妙。
一开始,我的想法是:在bfs是搜索过程中带着状态变量con(表示是否遇到过墨菲斯托或莉莉丝,两个都遇到了这个路线就不成立,可以pop掉。)但是发现这样vis数组会其冲突,压缩起来会比较麻烦。
参考大佬的解法:分两次bfs
第一次,将墨菲斯托的位置全部设为无法进入,莉莉丝设为空房间,bfs一次,得出最短路。这一步的目的是:求出不经过墨菲斯托所在位置能不能得到书,能的话,返回最短距离,不能则返回-1。
第二次反过来,墨菲斯托设为空房间,莉莉丝设为无法进入,再进行一次bfs。同样的,这一步的求出不经过莉莉丝能不能得到书。
然后,综合两次结果得出结论:
若两个结果都是-1,说明不管怎么走,都会遇到墨菲斯托,并且都会遇到莉莉丝,因此,IMPOSSIBLE
若只有其中一个不是-1,说明一个是一定要遇到的,另一个可以不遇到,那就输出不为-1的那一个。
否则,两个都不是-1,都可以不遇到,那当然取min的那个。
为什么这道题可以这么做呢?因为两个人中一定需要有一个遇不到才存在可行方案,所以,我们可以分两次bfs,得出是否存在方案可以避开两人中的一人,来判断是不是IMPOSSIBLE。

#include <iostream>
#include <map>
#include <ctime>
#include <vector>
#include <climits>
#include <algorithm>
#include <random>
#include <cstring>
#include <cstdio>
#include <map>
#include <set>
#include <bitset> 
#include <queue>
#define inf 0x3f3f3f3f
#define IOS ios_base::sync_with_stdio(0); cin.tie(0);
#define rep(i, a, n) for(register int i = a; i <= n; ++ i)
#define per(i, a, n) for(register int i = n; i >= a; -- i)
//#define ONLINE_JUDGE
using namespace std;
typedef long long ll;
const int mod=1e9+7;
template<typename T>void write(T x)
{
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    if(x>9)
    {
        write(x/10);
    }
    putchar(x%10+'0');
}

template<typename T> void read(T &x)
{
    x = 0;char ch = getchar();ll f = 1;
    while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
    while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;};
ll ksm(ll a,ll n){//看是否要mod 
    ll ans=1;
    while(n){
        if(n&1) ans=(ans*a)%mod;
        a=a*a%mod;
        n>>=1;
    }
    return ans%mod;
}
//==============================================================
const int maxn=1e3+10;
int t,n,m,r,c;
struct node{
    int x,y,step;
    node(int xx,int yy,int sp){
        x=xx,y=yy,step=sp;
    }
};
char a[maxn][maxn];
char mp[maxn][maxn];
int vis[maxn][maxn]={0};
int dir[4][2]={1,0,-1,0,0,1,0,-1};
int bfs(){
    memset(vis,0,sizeof(vis));
    queue<node> que;
    que.push(node(1,1,0));
    vis[1][1]=1;
    while(!que.empty()){
        node a=que.front();
        que.pop();
        if(a.x==r&&a.y==c){
            return 2*a.step;
        }
        rep(i,0,3){
            int dx=a.x+dir[i][0],dy=a.y+dir[i][1];
            if(vis[dx][dy]||dx<=0||dy<=0||dx>n||dy>m||mp[dx][dy]=='*') continue;
            vis[dx][dy]=1;
            node tmp(dx,dy,a.step+1);
            que.push(tmp);
        }
    }
    return -1;
}

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif
    //===========================================================
    read(t);
    while(t--){
        memset(vis,0,sizeof(vis));
        read(n),read(m),read(r),read(c);
        rep(i,1,n){
            rep(j,1,m){
                cin>>a[i][j];
            }
        }
        rep(i,1,n){
            rep(j,1,m){
                if(a[i][j]=='M'){
                    mp[i][j]='*';
                }
                else if(a[i][j]=='F'){
                    mp[i][j]='.';
                }
                else mp[i][j]=a[i][j];
            }
        }
        int ans1=bfs();
        rep(i,1,n){
            rep(j,1,m){
                if(a[i][j]=='F'){
                    mp[i][j]='*';
                }
                else if(a[i][j]=='M'){
                    mp[i][j]='.';
                }
                else{
                    mp[i][j]=a[i][j];
                }
            }
        }
        int ans2=bfs();
        if(ans1==-1&&ans2==-1){
            puts("IMPOSSIBLE");
        }
        else if(ans1==-1||ans2==-1){
            write(max(ans1,ans2)),putchar('\n');
        }
        else{
            write(min(ans1,ans2)),putchar('\n');
        }

    }
    //===========================================================
    return 0;
}