#include<cstdio>
#include<vector>
#include<map>
#include<set>
#include<queue>

using namespace std;

const int MAX_STATES_OR_SWAP = 37*1000*1000;

typedef pair<int, int> pii;
typedef pair< pii, set< pii > > state;

int width, height, boxes_cnt, man_row, man_col;
vector< vector<bool> > isWall;
set< pii > boxes, targets;

map< state, int > length;
set< pii > reachable_tiles;

void read() {
    if (scanf("%d %d", &width, &height) != 2) exit(1);
    isWall.resize(height, vector<bool>(width));
    for (int r = 0; r<height; ++r) {
        for (int c = 0; c<width; ++c) {
            int wall;
            if (scanf("%d", &wall) != 1) exit(1);;
            isWall[r][c] = wall == 1;
        }
    }

    if (scanf("%d", &boxes_cnt) != 1) exit(1);;
    for (int i = 0; i<boxes_cnt; ++i) {
        int r,c;
        if (scanf("%d %d", &r, &c) != 2) exit(1);;
        boxes.insert({r, c});
    }
    for (int i = 0; i<boxes_cnt; ++i) {
        int r,c;
        if( scanf("%d %d", &r, &c) != 2) exit(1);
        targets.insert({r, c});
    }

    if (scanf("%d %d", &man_row, &man_col) != 2) exit(1);
}

state move(pii man, const set< pii> &boxes, int dr, int dc) {
    int nr = man.first + dr;
    int nc = man.second + dc;
    // Cannot walk through walls.
    if (isWall[nr][nc]) {
        return {man, boxes};
    }
    // Doesn't push any boxes.
    if (boxes.find({nr, nc}) == boxes.end()) {
        return {{nr, nc}, boxes};
    }
    int nbr = nr + dr;
    int nbc = nc + dc;
    // Trying to push two boxes at once.
    if (boxes.find({nbr, nbc}) != boxes.end()) {
        return {man, boxes};
    }
    // If pushing box to the wall.
    if (isWall[nbr][nbc]) {
        return {man, boxes};
    }
    set< pii > new_boxes(boxes);
    new_boxes.erase({nr, nc});
    new_boxes.insert({nbr, nbc});
    return {{nr, nc}, new_boxes};
}

int bfs() {
    int dr[4] = {0,1,0,-1};
    int dc[4] = {1,0,-1,0};

    queue< state > q;
    state start_state = {{man_row, man_col}, boxes};

    q.push(start_state);
    length[start_state] = 0;
    int shortest = -1;
    int cnt = 1;

    reachable_tiles.insert({man_row, man_col});

    while (!q.empty()) {
        pii man;
        set< pii > boxes;
        tie(man, boxes) = q.front();
        q.pop();
        int len = length[{man, boxes}];
        for (int i = 0; i<4; ++i) {
            pii new_man;
            set< pii > new_boxes;
            tie(new_man, new_boxes) = move(man, boxes, dr[i], dc[i]);
            reachable_tiles.insert(new_man);
            state next_state = {new_man, new_boxes};

            // If I wasn't in this state.
            if (length.find(next_state) == length.end()) {
                length[next_state] = len+1;
                cnt++;
                if (new_boxes != targets) {
                    q.push(next_state);
                } else if (shortest == -1) {
                    shortest = len + 1;
                }
            }
        }
        if (cnt > MAX_STATES_OR_SWAP) {
            break;
        }
    }
    return shortest;
}

int main() {
    read();

    int shortest = bfs();
    int reachable_states = length.size();
    int reachable_tiles_cnt = reachable_tiles.size();

    printf("%d %d %d\n", shortest, reachable_states, reachable_tiles_cnt);

    return 0;
}
