#include<bits/stdc++.h>
using namespace std;
#define INF 1e9          // 定义无穷大,用于初始化最短时间
const int N=2e3+10;      // 定义地图的最大尺寸

// 全局变量定义
int n,m,sx,sy;           // n:地图行数 m:地图列数 sx:起点x坐标 sy:起点y坐标
char g[N][N];            // 存储地图信息的二维数组
int dis1[N][N];          // 存储所有传送门能到达的点的最短距离
int dis2[N][N];          // 存储起点出发能到达的点的最短距离
vector<pair<int,int>> transdoor; // 存储所有传送门(@)的坐标
int dx[4]={1,0,-1,0};    // 上下左右四个方向的x轴偏移量
int dy[4]={0,1,0,-1};    // 上下左右四个方向的y轴偏移量

// BFS1:计算所有传送门到地图上各点的最短距离
void bfs1(){
    // 初始化队列,将所有传送门的坐标加入队列(多源BFS)
    queue<pair<int,int>> qpr;
    for(int i=0;i<transdoor.size();i++){
        qpr.push({transdoor[i].first,transdoor[i].second});
        dis1[transdoor[i].first][transdoor[i].second]=0; // 传送门到自身的距离为0
    }
    
    // 多源BFS核心逻辑
    while(!qpr.empty()){
        pair<int,int> front=qpr.front();qpr.pop(); // 取出队首元素
        int x=front.first,y=front.second;          // 当前点的坐标
        int dis=dis1[x][y];                        // 当前点的最短距离
        
        // 遍历四个方向
        for(int i=0;i<4;i++){
            int tx=x+dx[i]; // 新点x坐标
            int ty=y+dy[i]; // 新点y坐标
            // 边界检查 + 障碍物检查 + 未访问过检查
            if(tx>=1&&tx<=n&&ty>=1&&ty<=m&&g[tx][ty]!='#'&&dis1[tx][ty]==-1){
                dis1[tx][ty]=dis+1; // 更新最短距离
                qpr.push({tx,ty});  // 加入队列继续搜索
            }
        }
    }
}

// BFS2:计算起点出发,主角和镜像同步移动能到达的点的最短距离
void bfs2(){
    queue<pair<int,int>> qpr;
    qpr.push({sx,sy});    // 起点入队
    dis2[sx][sy]=0;       // 起点到自身的距离为0
    
    while(!qpr.empty()){
        pair<int,int> front=qpr.front();qpr.pop(); // 取出队首元素
        int x=front.first,y=front.second;          // 当前主角位置
        int jx=2*sx-x;    // 镜像的x坐标(以起点为中心对称)
        int jy=2*sy-y;    // 镜像的y坐标(以起点为中心对称)
        
        // 遍历四个移动方向
        for(int i=0;i<4;i++){
            // 主角移动后的新坐标
            int tx=x+dx[i];
            int ty=y+dy[i];
            // 镜像同步移动后的新坐标(与主角移动方向相反)
            int tjx=jx-dx[i];
            int tjy=jy-dy[i];
            
            // 边界检查:主角和镜像都不能越界,且都不能走到障碍物(#)上
            if(tx>=1&&tx<=n&&ty>=1&&ty<=m&&tjx>=1&&tjx<=n&&tjy>=1&&tjy<=m&&g[tx][ty]!='#'&&g[tjx][tjy]!='#'){
                // 如果主角新位置未访问过,更新距离并加入队列
                if(dis2[tx][ty]==-1){
                    qpr.push({tx,ty});
                    dis2[tx][ty]=dis2[x][y]+1;
                }
                // 如果镜像新位置未访问过,更新镜像位置的距离
                if(dis2[tjx][tjy]==-1){
                    dis2[tjx][tjy]=dis2[jx][jy]+1;
                }
            }
        }
    }
}

// 主逻辑处理函数:计算最小时间
void solve(){
    // 初始化距离数组为-1(-1表示不可达)
    memset(dis1,-1,sizeof(dis1));
    memset(dis2,-1,sizeof(dis2));
    
    // 执行两次BFS,分别计算传送门和起点的最短距离
    bfs1();
    bfs2();
    
    int res_time=INF; // 初始化最小时间为无穷大
    
    // 遍历地图上所有点,寻找最优解
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            // 只处理起点能到达的点
            if(dis2[i][j]!=-1){
                int t1=dis2[i][j];                // 起点到(i,j)的时间
                int jx=2*sx-i;                    // (i,j)对应的镜像位置x
                int jy=2*sy-j;                    // (i,j)对应的镜像位置y
                
                // 情况1:当前位置是传送门,且镜像位置能被其他传送门到达
                if(g[i][j]=='@'&&dis1[jx][jy]!=-1){
                    res_time=min(res_time,t1+dis1[jx][jy]);
                }
                // 情况2:镜像位置是传送门,且当前位置能被其他传送门到达
                if(g[jx][jy]=='@'&&dis1[i][j]!=-1){
                    res_time=min(res_time,t1+dis1[i][j]);
                }
            }
        }
    }
    
    // 输出结果:如果最小时间还是无穷大则输出-1,否则输出最小时间
    if(res_time==INF){
        cout<<-1<<endl;
    }else{
        cout<<res_time<<endl;
    }
    return;
}

int main(){
    // 输入地图尺寸和起点坐标
    cin>>n>>m>>sx>>sy;
    // 输入地图信息,并收集所有传送门的坐标
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            cin>>g[i][j];
            if(g[i][j]=='@'){ // 识别传送门并存储坐标
                transdoor.push_back({i,j});
            }
        }
    }
    
    // 执行核心逻辑
    solve();

    return 0;
}