#include <bits/stdc++.h>
using namespace std;
using Coor = pair<int, int>;
int m, n;
Coor start = make_pair(1, 1);
class Node {
 private:
  vector<Coor> posset;
  int left, right, top, bottom;

 public:
  list<list<Node>::iterator> arcs;
  int shortestpath;
  bool termination = false;
  bool starter = false;
  Node(Coor first) {
    posset.resize(0);
    left = right = first.second;
    top = bottom = first.first;
    posset.push_back(first);
    arcs.clear();
    if (first == start) starter = true;
    shortestpath = 0x3f3f3f;
    return;
  }
  bool adja(Coor& target) {
    if (target.first <= bottom + 1 && target.first >= top - 1 &&
        target.second <= right + 1 && target.second >= left - 1) {
      for (auto& member : posset) {
        if ((target.first == member.first &&
             abs(target.second - member.second) == 1) ||
            (target.second == member.second &&
             abs(target.first - member.first) == 1))
          return true;
      }
    }
    return false;
  }
  void add(Coor& target) {
    left = min(left, target.second);
    right = max(right, target.second);
    top = min(top, target.first);
    bottom = max(bottom, target.first);
    posset.push_back(target);
    if (target == start) starter = true;
    return;
  }
  void merge(Node& target) {
    for (auto& pos : target.posset) this->add(pos);
    termination |= target.termination;
    starter |= target.starter;
    return;
  }
  bool reachable(Node& target) {
    if (((left < target.left && right + 2 < target.left) ||
         (right > target.right && left - 2 > target.right)) &&
        ((top < target.top && bottom + 2 < target.top) ||
         bottom > target.bottom && top - 2 > target.bottom)) {
      return false;
    }
    return true;
  }
};
class graph {
 private:
  list<Node> vertex;
  list<Node>::iterator termpos;
  list<Node>::iterator startpos;

 public:
  graph() {
    Node temp(make_pair(n + 1, m + 1));
    temp.termination = true;
    vertex.push_back(move(temp));
    termpos = vertex.end();
    return;
  }
  void add(Coor target) {
    vector<list<Node>::iterator> adjNodes;
    bool specialcondition = false;
    if (target == make_pair(n, m)) specialcondition = true;
    for (auto nodeit = vertex.begin(); nodeit != vertex.end(); nodeit++) {
      if (nodeit->adja(target) || (nodeit->termination && specialcondition))
        adjNodes.push_back(nodeit);
    }
    if (adjNodes.empty()) {
      Node temp(target);
      vertex.push_back(move(temp));
    } else if (adjNodes.size() == 1) {
      adjNodes[0]->add(target);
    } else {
      adjNodes[0]->add(target);
      for (auto& it : adjNodes) {
        if (it != adjNodes[0]) {
          adjNodes[0]->merge(*it);
          vertex.erase(it);
        }
      }
    }
    return;
  }
  void buildarc() {
    for (auto it1 = vertex.begin(); it1 != vertex.end(); it1++) {
      auto it2 = it1;
      it2++;
      if (it1->termination) termpos = it1;
      if (it1->starter) startpos = it1;
      for (; it2 != vertex.end(); it2++) {
        if (it1->reachable(*it2)) {
          it1->arcs.push_back(it2);
          it2->arcs.push_back(it1);
        }
      }
    }
  }
  void findshortpath() {
    queue<list<Node>::iterator> bfs;
    bfs.push(startpos);
    startpos->shortestpath = 0;
    while (!bfs.empty()) {
      auto current = bfs.front();
      bfs.pop();
      for (auto& it : current->arcs) {
        if (it->shortestpath > current->shortestpath + 1) {
          it->shortestpath = current->shortestpath + 1;
          bfs.push(it);
        }
      }
    }
    return;
  }
  void outputshortpath() {
    if (termpos->shortestpath == 0x3f3f3f)
      cout << -1 << endl;
    else
      cout << (termpos->shortestpath) << endl;
    return;
  }
};
int main() {
  int k, first, second;
  cin >> n >> m >> k;
  graph table;
  for (int i = 0; i < k; i++) {
    cin >> first >> second;
    table.add(make_pair(first, second));
  }
  table.buildarc();
  table.findshortpath();
  table.outputshortpath();
  return 0;
}
