#include <iostream>
#include <queue>
#include <algorithm>
#include <cstring>
using namespace std;
int n, m , s_x, s_y;
char c[2005][2005];
int dist[2005][2005][2];
int direction[4][2] = {{-1, 0}, {1, 0}, {0, 1}, {0, -1}};
//int vis[11][11][10005];
//struct status {
// int x;
// int y;
// int cost;
// int modVal;
//};
struct status {
int x;
int y;
int flag;
};
//C++大小写敏感,且可以直接const int == int会有隐式转换
const int MIN_VAL = 10000000;
//1.将两个点变成一个点的约束
//2.引入flag这个维度状态
//3.状态之间是怎么转换的
int main() {
cin >> n >> m >> s_x >> s_y;
// p--;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cin >> c[i][j];
}
}
memset(dist, 0xFF, sizeof(dist));
queue<status> q;
status st;
st.x = s_x;
st.y = s_y;
st.flag = 0;
dist[st.x][st.y][st.flag] = 0;
q.push(st);
int minVal = MIN_VAL;
while (!q.empty()) {
status s = q.front();
q.pop();
if (s.flag && c[s.x][s.y] == '@') {
minVal = min(minVal, dist[s.x][s.y][s.flag]);
}
for (int i = 0; i < 4; i++) {
int x = s.x + direction[i][0];
int y = s.y + direction[i][1];
//求x, y关于s_x, s_y的对称点
int x_2 = 2 * s_x - x;
int y_2 = 2 * s_y - y;
//falg = 1之后的对称点不受限制
if (x <= n && x > 0 && y <= m && y > 0 && c[x][y] != '#' && (s.flag || (x_2 <= n && x_2 > 0 && y_2 <= m && y_2 > 0 && c[x_2][y_2] != '#' && !(c[x_2][y_2] != '@' && c[x][y] == '@')))) {
//根据之前点位的flag赋值
int new_flag = s.flag;
if (!new_flag) {
new_flag = c[x_2][y_2] == '@' ? 1 : 0;
}
//没访问过更新,加入队列扩展
if (dist[x][y][new_flag] < 0) {
status new_s;
new_s.x = x;
new_s.y = y;
new_s.flag = new_flag;
dist[x][y][new_flag] = dist[s.x][s.y][s.flag] + 1;
q.push(new_s);
}
}
}
}
cout << (minVal == MIN_VAL ? -1 : minVal) << endl;
}