#include <vector>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> P;
typedef double db;

#define fr first
#define sc second
#define pb push_back
#define rep(i,x) for(ll i=0;i<x;i++)
#define rep1(i,x) for(ll i=1;i<=x;i++)
#define rrep(i,x) for(ll i=x-1;i>=0;i--)
#define rrep1(i,x) for(ll i=x;i>0;i--)
struct T{
	ll y,x,id;
};
struct edge{
	ll to,cost;
};
struct A{
	ll cost,id,dir;
	bool operator<(const A& an)const{
		return cost<an.cost;
	}
	bool operator>(const A& an)const{
		return cost>an.cost;
	}
};
vector<edge> G[200002][2];
ll H,W,N;
ll d[200002][2];//0?????? 1??±?\?
T sw[200001];
const ll INF = 0xffffffffffffff;
bool start;
int main()
{
	cin>>W>>H>>N;
	rep1(i,N){
		cin>>sw[i].x>>sw[i].y;
		if(sw[i].x==W&&sw[i].y==H){
			N--;
			i--;
			continue;
		}
		if(sw[i].x==1&&sw[i].y==1) {
			start=1;
			N--;
			i--;
			continue;
		}
		sw[i].y--;
		sw[i].x--;
		sw[i].id=i;
	}
	sort(sw+1,sw+N+1,[](T a,T b){
			return a.x==b.x?a.y<b.y:a.x<b.x;
	});
	if(sw[N].x==W-1){
		G[sw[N].id][0].pb(edge{N+1,H-1-sw[N].y});
	}
	if(sw[1].x==0){
		G[0][0].pb(edge{sw[1].id,sw[1].y});
	}
	rep1(i,N-1){
		if(sw[i].x==sw[i+1].x){
			G[sw[i].id][0].pb(edge{sw[i+1].id,sw[i+1].y-sw[i].y});
			G[sw[i+1].id][0].pb(edge{sw[i].id,sw[i+1].y-sw[i].y});
		}
	}
	sort(sw+1,sw+N+1,[](T a,T b){
			return a.y==b.y?a.x<b.x:a.y<b.y;
	});
	if(start&&sw[1].y==0){
		G[0][1].pb(edge{sw[1].id,sw[1].x});
	}
	if(sw[N].y==H-1){
		G[sw[N].id][1].pb(edge{N+1,W-1-sw[N].x});
	}
	rep1(i,N-1){
		if(sw[i].y==sw[i+1].y){
			G[sw[i].id][1].pb(edge{sw[i+1].id,sw[i+1].x-sw[i].x});
			G[sw[i+1].id][1].pb(edge{sw[i].id,sw[i+1].x-sw[i].x});
		}
	}
	N++;//0st Ngoal
	fill(d[0],d[200002],INF);
	d[0][0]=0;
	priority_queue<A,vector<A>,greater<A> > q;
	q.push(A{0,0,0});
	if(start){
		d[0][1]=1;
		q.push(A{0,0,1});
	}
	while(!q.empty()){
		A p=q.top();
		q.pop();
		ll x=p.id;
		ll y=p.dir;
		if(d[x][y]<p.cost) continue;
		if(x!=0&&x!=N){
			if(d[x][!y]>d[x][y]+1){
				d[x][!y]=d[x][y]+1;
				q.push(A{d[x][!y],x,!y});
			}
		}
		rep(i,G[x][y].size()){
			edge e=G[x][y][i];
			if(d[e.to][y]>d[x][y]+e.cost){
				d[e.to][y]=d[x][y]+e.cost;
				q.push(A{d[e.to][y],e.to,y});
			}
		}
	}
	if(d[N][0]==INF&&d[N][1]==INF) cout<<"-1"<<endl;
	else cout<<min(d[N][0],d[N][1])<<endl;
}