#include<iostream>
#include<cstdio>
#include<vector>
#include<deque>
#include<algorithm>
#include<cassert>
#include<queue>
#include<climits>
#include<cstring>
#include<map>

#define REP(i,s,n) for(int i=s;i<n;++i)
#define rep(i,n) REP(i,0,n)
#define ALL(x) x.begin(),x.end()

using namespace std;

typedef long long ll;

int H,W,N;

struct Point { 
  int x,y,b;
  Point(int x=-1,int y=-1,int b=1):x(x),y(y),b(b){}
  bool operator < ( const Point &p ) const {
    if( x != p.x ) return x < p.x;
    return y < p.y;
  }
};

bool cmp(const Point &a,const Point &b) {
  if( a.y != b.y ) return a.y < b.y;
  return a.x < b.x;
}

struct Data {
  int cur,dir;
  ll cost;
  bool operator < ( const Data &data ) const {
    if( cost != data.cost ) return cost > data.cost;
    if( cur != data.cur ) return cur < data.cur;
    return dir < data.dir;
  }
};

void compute(deque<Point> &ps) {
  sort(ALL(ps));
  if( !( ps[0].x == 1 && ps[0].y == 1 ) ) {
    ps.push_front((Point){1,1,0});
  }
  if( !( ps[(int)ps.size()-1].x == W && ps[(int)ps.size()-1].y == W ) ) {
    ps.push_back((Point){W,H,0});
  }


  int n = ps.size();
  deque<Point> vec = ps;
  vector<vector<int>> edges(n);


  rep(i,n) {
    int ptr = lower_bound(ALL(ps),ps[i]) - ps.begin();
    if( ptr - 1 >= 0 ) {
      if( vec[i].x == vec[ptr-1].x ) {
	edges[i].push_back(ptr-1);
      }
    }
    if( ptr + 1 <  n ) {
      if( vec[i].x == vec[ptr+1].x ) {
	edges[i].push_back(ptr+1);
      }
    }
  }

  sort(ALL(ps),cmp);

  rep(i,n) {
    int ptr = lower_bound(ALL(ps),ps[i],cmp) - ps.begin();
    if( ptr - 1 >= 0 ) {
      int ID  = lower_bound(ALL(vec),ps[ptr])    - vec.begin();
      int adj = lower_bound(ALL(vec),ps[ptr-1]) - vec.begin();
      assert( adj < n );
      if( vec[ID].y == vec[adj].y ) {
	edges[ID].push_back(adj);
      }
    }
    if( ptr + 1 < n ) {
      int ID  = lower_bound(ALL(vec),ps[ptr])   - vec.begin();
      int adj = lower_bound(ALL(vec),ps[ptr+1]) - vec.begin();
      assert( adj < n );
      if( vec[ID].y == vec[adj].y ) {
	edges[ID].push_back(adj);
      }
    }
  }

  rep(i,n) {
    sort(ALL(edges[i]));
    edges[i].erase(unique(ALL(edges[i])),edges[i].end());
  }

  priority_queue<Data> Q;
  vector<vector<ll>> mini(n,vector<ll>(2,LLONG_MAX));
  mini[0][0] = 0;
  Q.push((Data){0,0,0});
  
  while( !Q.empty() ) {
    Data data = Q.top(); Q.pop();
    if( vec[data.cur].b && mini[data.cur][(data.dir+1)&1] > data.cost + 1 ) {
      mini[data.cur][(data.dir+1)&1] = data.cost + 1;
      Q.push((Data){data.cur,(data.dir+1)&1,data.cost+1});
    }
    rep(i,(int)edges[data.cur].size()) {
      int next = edges[data.cur][i];
      int cost = abs(vec[data.cur].x-vec[next].x + vec[data.cur].y-vec[next].y);
      if( data.dir ) {
	if( vec[next].y == vec[data.cur].y ) {
	  if( mini[next][data.dir] > data.cost + cost ) {
	    mini[next][data.dir] = data.cost + cost;
	    Q.push((Data){next,data.dir,data.cost+cost});
	  }
	}
      } else {
	if( vec[next].x == vec[data.cur].x ) {
	  if( mini[next][data.dir] > data.cost + cost ) {
	    mini[next][data.dir] = data.cost + cost;
	    Q.push((Data){next,data.dir,data.cost+cost});
	  }
	}
      }      
    }
  }
  ll ans = min(mini[n-1][0],mini[n-1][1]);
  if( ans == LLONG_MAX ) puts("-1");
  else printf("%lld\n",ans);
}


int main() {
  scanf("%d %d %d",&W,&H,&N);
  deque<Point> ps(N);
  rep(i,N) scanf("%d %d",&ps[i].x,&ps[i].y);
  compute(ps);
  return 0;
}

Measured memory_bytes: 30620