import java.io.*;
import java.util.*;

public class D {

	public static void main(String[] args) {
		FastScanner sc = new FastScanner();
		int n = sc.nextInt();
		int m = sc.nextInt();
		int k = sc.nextInt();
		HashSet<Integer>[] byrow = new HashSet[n];
		for(int i = 0; i < n; i++) byrow[i] = new HashSet<>();
		HashSet<Integer>[] bycol = new HashSet[m];
		for(int i = 0; i < m; i++) bycol[i] = new HashSet<>();
		for(int i = 0; i < k; i++) {
			int x = sc.nextInt()-1;
			int y = sc.nextInt()-1;
//			Coor c = new Coor(x, y);
			byrow[x].add(y);
			bycol[y].add(x);
		}
		Coor c0 = new Coor(0, 0, 0);
		int[][] dist = new int[n][m];
		for(int i = 0; i < n; i++) {
			for(int j = 0; j < m; j++) {
				dist[i][j] = 1000000000;
			}
		}
		dist[0][0] = 0;
		PriorityQueue<Coor> q = new PriorityQueue<>();
		q.add(c0);
		int[][] dir = {{0, 1}, {0, -1}, {1,0}, {0,1}};
		while(!q.isEmpty()) {
			Coor c = q.poll();
			for(int[] d: dir) {
				int x = c.x + d[0], y = c.y + d[1];
				if(x >= 0 && y >= 0 && x < n && y < m && byrow[x].contains(y) && dist[x][y] > dist[c.x][c.y]+0) {
					dist[x][y] = dist[c.x][c.y];
					q.add(new Coor(x, y, dist[x][y]));
				}
			}
			for(int dx = -2; dx <= 2; dx++) {
				if(c.x+dx >= 0 && c.x+dx < n) {
					for(int y: byrow[c.x+dx]) {
						if(dist[c.x+dx][y] > dist[c.x][c.y]+1) {
							dist[c.x+dx][y] = dist[c.x][c.y]+1;
							q.add(new Coor(c.x+dx,y,dist[c.x+dx][y]));
						}
					}
				}
			}
			for(int dy = -2; dy <= 2; dy++) {
				if(c.y+dy >= 0 && c.y+dy < m) {
					for(int x: bycol[c.y+dy]) {
						if(dist[x][c.y+dy] > dist[c.x][c.y]+1) {
							dist[x][c.y+dy] = dist[c.x][c.y]+1;
							q.add(new Coor(x,c.y+dy,dist[x][c.y+dy]));
						}
					}
				}
			}
		}
		int res = dist[n-1][m-1];
		for(int y: byrow[n-1]) {
			res = Math.min(res, dist[n-1][y]+1);
		}
		for(int y: byrow[n-2]) {
			res = Math.min(res, dist[n-2][y]+1);
		}
		for(int x: bycol[m-1]) {
			res = Math.min(res, dist[x][m-1]+1);
		}
		for(int x: bycol[m-2]) {
			res = Math.min(res, dist[x][m-2]+1);
		}
		if(res == 1000000000) System.out.println(-1);
		else System.out.println(res);
	}
	static class Coor implements Comparable<Coor>{
		int x, y, w;
		public Coor(int x, int y, int w) {
			this.x = x; this.y = y; this.w = w;
		}
		public int compareTo(Coor c) {
			return w - c.w;
		}
//		@Override
//		public int hashCode() {
//			return x+y;
//		}
//		@Override
//		public boolean equals(Object o) {
//			Coor c = (Coor)o;
//			return x == c.x && y == c.y;
//		}
	}

	static class FastScanner {
		public BufferedReader reader;
		public StringTokenizer tokenizer;
		public FastScanner() {
			reader = new BufferedReader(new InputStreamReader(System.in), 32768);
			tokenizer = null;
		}
		public String next() {
			while (tokenizer == null || !tokenizer.hasMoreTokens()) {
				try {
					tokenizer = new StringTokenizer(reader.readLine());
				} catch (IOException e) {
					throw new RuntimeException(e);
				}
			}
			return tokenizer.nextToken();
		}
		public int nextInt() {
			return Integer.parseInt(next());
		}
		public long nextLong() {
			return Long.parseLong(next());
		}
		public double nextDouble() {
			return Double.parseDouble(next());
		}
		public String nextLine() {
			try {
				return reader.readLine();
			} catch(IOException e) {
				throw new RuntimeException(e);
			}
		}
	}

}


import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;

public class d {
	static class Node{
		int r, c;
		int dist = 999_999_999;
		ArrayList<Node> zeroes = new ArrayList<>(1);
		ArrayList<Node> ones = new ArrayList<>(1);
		Node(int xx, int yy){
			r = xx; c = yy;
		}
	}
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		// PITFALL! the bottom right cell is NOT NECESSARILY LIT!
		int N = in.nextInt(), M = in.nextInt(), K = in.nextInt();
		ArrayList<Node> byR = new ArrayList<>();
		ArrayList<Node> byC = new ArrayList<>();
		boolean bottomRightIsLit = false;
		Node bottom = null;
		for(int k=0;k<K;k++){
			int r = in.nextInt(), c = in.nextInt();
			Node node = new Node(r,c);
			if(r == N && c == M){
				bottomRightIsLit = true;
				bottom = node;
			}
			byR.add(node);
			byC.add(node);
		}
		Collections.sort(byR, (a,b)->{
			if(a.r - b.r != 0) return a.r - b.r;
			return a.c - b.c;
		});
		Collections.sort(byC, (a,b)->{
			if(a.c - b.c != 0) return a.c - b.c;
			return a.r - b.r;
		});

		Node prev;

		// connect horizontally adjacent cells
		prev = null;
		for(Node node : byR){
			if(prev != null){
				if(prev.r == node.r && prev.c + 1 == node.c){
					// connect these two with a zero edge
					prev.zeroes.add(node);
					node.zeroes.add(prev);
				}
			}
			prev = node;
		}

		// connect vertically adjacent cells
		prev = null;
		for(Node node : byC){
			if(prev != null){
				if(prev.c == node.c && prev.r + 1 == node.r){
					// connect these two with a zero edge
					prev.zeroes.add(node);
					node.zeroes.add(prev);
				}
			}
			prev = node;
		}

		Node[] rowHub = new Node[N+1];
		Node[] colHub = new Node[M+1];
		for(int n=0;n<=N;n++) rowHub[n] = new Node(n+1,-1);
		for(int m=0;m<=M;m++) colHub[m] = new Node(-1,m+1);
		for(Node node : byR){
			// connect this node to its rowHub and colHub, and the ones adjacent
			node.ones.add(rowHub[node.r]);
			rowHub[node.r].zeroes.add(node);
			if(node.r+1 <= N){
				node.ones.add(rowHub[node.r+1]);
				rowHub[node.r+1].zeroes.add(node);
			}
			if(node.r-1 > 0){
				node.ones.add(rowHub[node.r-1]);
				rowHub[node.r-1].zeroes.add(node);
			}
			node.ones.add(colHub[node.c]);
			colHub[node.c].zeroes.add(node);
			if(node.c+1 <= N){
				node.ones.add(colHub[node.c+1]);
				colHub[node.c+1].zeroes.add(node);
			}
			if(node.c-1 > 0){
				node.ones.add(colHub[node.c-1]);
				colHub[node.c-1].zeroes.add(node);
			}

		}

		// the graph is now connected
		// WAIT
		if(!bottomRightIsLit){
			// aw dammit, gotta take this into account
			// this cell missed any action allowing it to have any bottom
			// so it is not gonna connect to any other lights in the normal way
			bottom = new Node(N,M);
			rowHub[N].zeroes.add(bottom);
			colHub[M].zeroes.add(bottom);
//			rowHub[N-1].zeroes.add(bottom);
//			colHub[M-1].zeroes.add(bottom);
		}

		// okay, now onto the zero-one BFS
		// for some reason, every time i code a 0-1 BFS with one deque, i get wrong answer
		// so i'm not gonna do that
		// i'll have two queues
		ArrayDeque<Node> oneQ = new ArrayDeque<>(N+M+K+1);
		ArrayDeque<Node> zeroQ = new ArrayDeque<>(N+M+K+1);
		byR.get(0).dist = 0;
		oneQ.add(byR.get(0));

		while(!oneQ.isEmpty()){
			Node onePoll = oneQ.pop();
			zeroQ.add(onePoll);
			while(!zeroQ.isEmpty()){
				Node zeroPoll = zeroQ.pop();
				for(Node next : zeroPoll.zeroes){
					if(next.dist > zeroPoll.dist){
						next.dist = zeroPoll.dist;
						zeroQ.add(next);
					}
				}
				for(Node next : zeroPoll.ones){
					if(next.dist == 999_999_999){
						next.dist = 1 + zeroPoll.dist;
						oneQ.add(next);
					}
				}
			}
		}

		if(bottom.dist == 999_999_999){
			System.out.println(-1);
		}
		else{
			System.out.println(bottom.dist);
		}
	}
}


import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;

public class d {
	static class Node{
		int r, c;
		int dist = 999_999_999;
		ArrayList<Node> zeroes = new ArrayList<>(1);
		ArrayList<Node> ones = new ArrayList<>(1);
		Node(int xx, int yy){
			r = xx; c = yy;
		}
	}
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		// PITFALL! the bottom right cell is NOT NECESSARILY LIT!
		int N = in.nextInt(), M = in.nextInt(), K = in.nextInt();
		ArrayList<Node> byR = new ArrayList<>();
		ArrayList<Node> byC = new ArrayList<>();
		boolean bottomRightIsLit = false;
		Node bottom = null;
		for(int k=0;k<K;k++){
			int r = in.nextInt(), c = in.nextInt();
			Node node = new Node(r,c);
			if(r == N && c == M){
				bottomRightIsLit = true;
				bottom = node;
			}
			byR.add(node);
			byC.add(node);
		}
		Collections.sort(byR, (a,b)->{
			if(a.r - b.r != 0) return a.r - b.r;
			return a.c - b.c;
		});
		Collections.sort(byC, (a,b)->{
			if(a.c - b.c != 0) return a.c - b.c;
			return a.r - b.r;
		});

		Node prev;

		// connect horizontally adjacent cells
		prev = null;
		for(Node node : byR){
			if(prev != null){
				if(prev.r == node.r && prev.c + 1 == node.c){
					// connect these two with a zero edge
					prev.zeroes.add(node);
					node.zeroes.add(prev);
				}
			}
			prev = node;
		}

		// connect vertically adjacent cells
		prev = null;
		for(Node node : byC){
			if(prev != null){
				if(prev.c == node.c && prev.r + 1 == node.r){
					// connect these two with a zero edge
					prev.zeroes.add(node);
					node.zeroes.add(prev);
				}
			}
			prev = node;
		}

		Node[] rowHub = new Node[N+1];
		Node[] colHub = new Node[M+1];
		for(int n=0;n<=N;n++) rowHub[n] = new Node(n+1,-1);
		for(int m=0;m<=M;m++) colHub[m] = new Node(-1,m+1);
		for(Node node : byR){
			// connect this node to its rowHub and colHub, and the ones adjacent
			node.ones.add(rowHub[node.r]);
			rowHub[node.r].zeroes.add(node);
			if(node.r+1 <= N){
				node.ones.add(rowHub[node.r+1]);
				rowHub[node.r+1].zeroes.add(node);
			}
			if(node.r-1 > 0){
				node.ones.add(rowHub[node.r-1]);
				rowHub[node.r-1].zeroes.add(node);
			}
			node.ones.add(colHub[node.c]);
			colHub[node.c].zeroes.add(node);
			if(node.c+1 <= M){
				node.ones.add(colHub[node.c+1]);
				colHub[node.c+1].zeroes.add(node);
			}
			if(node.c-1 > 0){
				node.ones.add(colHub[node.c-1]);
				colHub[node.c-1].zeroes.add(node);
			}

		}

		// the graph is now connected
		// WAIT
		if(!bottomRightIsLit){
			// aw dammit, gotta take this into account
			// this cell missed any action allowing it to have any bottom
			// so it is not gonna connect to any other lights in the normal way
			bottom = new Node(N,M);
			rowHub[N].zeroes.add(bottom);
			colHub[M].zeroes.add(bottom);
//			rowHub[N-1].zeroes.add(bottom);
//			colHub[M-1].zeroes.add(bottom);
		}

		// okay, now onto the zero-one BFS
		// for some reason, every time i code a 0-1 BFS with one deque, i get wrong answer
		// so i'm not gonna do that
		// i'll have two queues
		ArrayDeque<Node> oneQ = new ArrayDeque<>(N+M+K+1);
		ArrayDeque<Node> zeroQ = new ArrayDeque<>(N+M+K+1);
		byR.get(0).dist = 0;
		oneQ.add(byR.get(0));

		while(!oneQ.isEmpty()){
			Node onePoll = oneQ.pop();
			zeroQ.add(onePoll);
			while(!zeroQ.isEmpty()){
				Node zeroPoll = zeroQ.pop();
				for(Node next : zeroPoll.zeroes){
					if(next.dist > zeroPoll.dist){
						next.dist = zeroPoll.dist;
						zeroQ.add(next);
					}
				}
				for(Node next : zeroPoll.ones){
					if(next.dist == 999_999_999){
						next.dist = 1 + zeroPoll.dist;
						oneQ.add(next);
					}
				}
			}
		}

		if(bottom.dist == 999_999_999){
			System.out.println(-1);
		}
		else{
			System.out.println(bottom.dist);
		}
	}
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.ArrayList;
import java.nio.charset.Charset;
import java.util.StringTokenizer;
import java.io.OutputStreamWriter;
import java.io.OutputStream;
import java.io.BufferedWriter;
import java.util.Collection;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UncheckedIOException;
import java.util.List;
import java.io.Writer;
import java.util.Queue;
import java.io.BufferedReader;
import java.util.ArrayDeque;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author mikit
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        LightScanner in = new LightScanner(inputStream);
        LightWriter out = new LightWriter(outputStream);
        DOkabeAndCity solver = new DOkabeAndCity();
        solver.solve(1, in, out);
        out.close();
    }

    static class DOkabeAndCity {
        public void solve(int testNumber, LightScanner in, LightWriter out) {
            // out.setBoolLabel(LightWriter.BoolLabel.YES_NO_FIRST_UP);
            int n = in.ints(), m = in.ints(), k = in.ints();
            Vec2i[] es = new Vec2i[k];
            for (int i = 0; i < k; i++) {
                es[i] = new Vec2i(in.ints(), in.ints());
            }

            int startIndex = -1;
            int goalIndex = -1;
            IntUnionFind uf = new IntUnionFind(k);
            for (int i = 0; i < k; i++) {
                for (int j = 0; j < i; j++) {
                    if (Math.abs(es[i].x - es[j].x) + Math.abs(es[i].y - es[j].y) == 1) {
                        uf.union(i, j);
                    }
                }
                if (es[i].x == 1 && es[i].y == 1) {
                    startIndex = i;
                } else if (es[i].x == n && es[i].y == m) {
                    goalIndex = i;
                }
            }

            int[] map = new int[k];
            Arrays.fill(map, -1);
            int cur = 0;
            for (int i = 0; i < k; i++) {
                int j = uf.find(i);
                if (map[j] >= 0) {
                    map[i] = map[j];
                } else {
                    map[i] = map[j] = cur;
                    cur++;
                }
            }

            int total = uf.size();
            if (goalIndex == -1) total++;
            DOkabeAndCity.Node[] nodes = new DOkabeAndCity.Node[total];
            for (int i = 0; i < total; i++) {
                nodes[i] = new DOkabeAndCity.Node();
            }

            for (int i = 0; i < k; i++) {
                int x = map[i];
                for (int j = 0; j < i; j++) {
                    if (Math.abs(es[i].x - es[j].x) + Math.abs(es[i].x - es[j].x) == 1) continue;
                    if (Math.abs(es[i].x - es[j].x) <= 2 || Math.abs(es[i].y - es[j].y) <= 2) {
                        int y = map[j];
                        if (x == y) continue;
                        if (nodes[x].neg.contains(nodes[y])) continue;
                        nodes[x].neg.add(nodes[y]);
                        nodes[y].neg.add(nodes[x]);
                    }
                }
            }

            DOkabeAndCity.Node goalNode;
            if (goalIndex == -1) {
                goalNode = nodes[total - 1];
                for (int i = 0; i < k; i++) {
                    if (es[i].x >= n - 1 || es[i].y >= m - 1) {
                        int y = map[i];
                        if (nodes[total - 1].neg.contains(nodes[y])) continue;
                        nodes[total - 1].neg.add(nodes[y]);
                        nodes[y].neg.add(nodes[total - 1]);
                    }
                }
                //System.out.println("USING INSTANT NODE");
            } else {
                goalNode = nodes[map[goalIndex]];
            }

            Queue<DOkabeAndCity.Node> q = new ArrayDeque<>();
            DOkabeAndCity.Node startNode = nodes[map[startIndex]];
            startNode.dist = 0;
            q.offer(startNode);
            while (!q.isEmpty()) {
                DOkabeAndCity.Node node = q.poll();
                for (DOkabeAndCity.Node next : node.neg) {
                    if (next.dist >= 0) continue;
                    next.dist = node.dist + 1;
                    q.offer(next);
                }
            }

            out.ans(goalNode.dist).ln();
        }

        private static class Node {
            private final List<DOkabeAndCity.Node> neg = new ArrayList<>();
            int dist = -1;

            public String toString() {
                return "Node{" +
                        "neg=" + neg.size() +
                        ", dist=" + dist +
                        '}';
            }

            public boolean equals(Object o) {
                return this == o;
            }

            public int hashCode() {
                return 0;
            }

        }

    }

    static final class IntUnionFind {
        private int groups;
        private final int[] nodes;
        private final int[] rank;

        public IntUnionFind(int n) {
            groups = n;
            nodes = new int[n];
            Arrays.fill(nodes, -1);
            rank = new int[n];
        }

        public int find(int i) {
            int ans = nodes[i];
            if (ans < 0) {
                return i;
            } else {
                return nodes[i] = find(ans);
            }
        }

        public int size() {
            return groups;
        }

        public boolean union(int x, int y) {
            x = find(x);
            y = find(y);
            if (x == y) {
                return false;
            } else if (rank[x] < rank[y]) {
                nodes[y] += nodes[x];
                nodes[x] = y;
            } else if (rank[x] == rank[y]) {
                rank[x]++;
                nodes[x] += nodes[y];
                nodes[y] = x;
            } else {
                nodes[x] += nodes[y];
                nodes[y] = x;
            }
            groups--;
            return true;
        }

    }

    static class Vec2i implements Comparable<Vec2i> {
        public int x;
        public int y;

        public Vec2i(int x, int y) {
            this.x = x;
            this.y = y;
        }

        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Vec2i vec2i = (Vec2i) o;
            return x == vec2i.x && y == vec2i.y;
        }

        public int hashCode() {
            return 31 * x + y;
        }

        public String toString() {
            return "(" + x + ", " + y + ")";
        }

        public int compareTo(Vec2i o) {
            if (x == o.x) {
                return Integer.compare(y, o.y);
            }
            return Integer.compare(x, o.x);
        }

    }

    static class LightWriter implements AutoCloseable {
        private final Writer out;
        private boolean autoflush = false;
        private boolean breaked = true;

        public LightWriter(Writer out) {
            this.out = out;
        }

        public LightWriter(OutputStream out) {
            this(new BufferedWriter(new OutputStreamWriter(out, Charset.defaultCharset())));
        }

        public LightWriter print(char c) {
            try {
                out.write(c);
                breaked = false;
            } catch (IOException ex) {
                throw new UncheckedIOException(ex);
            }
            return this;
        }

        public LightWriter print(String s) {
            try {
                out.write(s, 0, s.length());
                breaked = false;
            } catch (IOException ex) {
                throw new UncheckedIOException(ex);
            }
            return this;
        }

        public LightWriter ans(String s) {
            if (!breaked) {
                print(' ');
            }
            return print(s);
        }

        public LightWriter ans(int i) {
            return ans(Integer.toString(i));
        }

        public LightWriter ln() {
            print(System.lineSeparator());
            breaked = true;
            if (autoflush) {
                try {
                    out.flush();
                } catch (IOException ex) {
                    throw new UncheckedIOException(ex);
                }
            }
            return this;
        }

        public void close() {
            try {
                out.close();
            } catch (IOException ex) {
                throw new UncheckedIOException(ex);
            }
        }

    }

    static class LightScanner {
        private BufferedReader reader = null;
        private StringTokenizer tokenizer = null;

        public LightScanner(InputStream in) {
            reader = new BufferedReader(new InputStreamReader(in));
        }

        public String string() {
            if (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new UncheckedIOException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public int ints() {
            return Integer.parseInt(string());
        }

    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.io.BufferedWriter;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.util.InputMismatchException;
import java.io.IOException;
import java.io.InputStream;
/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        OutputWriter out = new OutputWriter(outputStream);
        TaskD solver = new TaskD();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskD {
        int MAX = 1000 * 1000 * 1000;

        public void solve(int testNumber, InputReader in, OutputWriter out) {
            int rows = in.readInt();
            int cols = in.readInt();
            int kLit = in.readInt();
            int[] rowLit = new int[kLit], colLit = new int[kLit];
            IOUtils.readIntArrays(in, rowLit, colLit);
            MiscUtils.decreaseByOne(rowLit, colLit);
            int[] dists = new int[kLit];
            Arrays.fill(dists, MAX);
            int res = MAX;
            for (int i = 0; i < kLit; i++) {
                if (rowLit[i] == 0 && colLit[i] == 0) {
                    dists[i] = 0;
                }
            }
            boolean[] visited = new boolean[kLit];
            while (true) {
                int bestDist = MAX;
                int bestIndex = -1;
                for (int i = 0; i < kLit; i++) {
                    if (!visited[i] && dists[i] < bestDist) {
                        bestDist = dists[i];
                        bestIndex = i;
                    }
                }
                if (bestIndex == -1) break;
                visited[bestIndex] = true;
                int row = rowLit[bestIndex];
                int col = colLit[bestIndex];
                int dist = dists[bestIndex];
                if (row == rows - 1 && col == cols - 1) { // we are there
                    res = Math.min(res, dist);
                }
                if (row == rows - 1 || col == cols - 1) { // we just need on more lit
                    res = Math.min(res, dist + 1);
                }
                if (row == rows - 2 || col == cols - 2) { // we are very close
                    res = Math.min(res, dist + 1);
                }
                for (int nxtIndex = 0; nxtIndex < kLit; nxtIndex++) {
                    if (nxtIndex != bestIndex) {
                        int nrow = rowLit[nxtIndex];
                        int ncol = colLit[nxtIndex];
                        if (Math.abs(row - nrow) + Math.abs(col - ncol) == 1) {
                            dists[nxtIndex] = Math.min(dists[nxtIndex], dist);
                        } else if (Math.abs(row - nrow) <= 2 || Math.abs(col - ncol) <= 2) {
                            dists[nxtIndex] = Math.min(dists[nxtIndex], dist + 1);
                        }
                    }
                }
            }
            out.printLine(res >= MAX ? -1 : res);
        }
    }
    static class MiscUtils {
        public static void decreaseByOne(int[]... arrays) {
            for (int[] array : arrays) {
                for (int i = 0; i < array.length; i++) {
                    array[i]--;
                }
            }
        }
    }
    static class InputReader {
        private InputStream stream;
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;
        private InputReader.SpaceCharFilter filter;

        public InputReader(InputStream stream) {
            this.stream = stream;
        }

        public int read() {
            if (numChars == -1) {
                throw new InputMismatchException();
            }
            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (numChars <= 0) {
                    return -1;
                }
            }
            return buf[curChar++];
        }

        public int readInt() {
            int c = read();
            while (isSpaceChar(c)) {
                c = read();
            }
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            int res = 0;
            do {
                if (c < '0' || c > '9') {
                    throw new InputMismatchException();
                }
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public boolean isSpaceChar(int c) {
            if (filter != null) {
                return filter.isSpaceChar(c);
            }
            return isWhitespace(c);
        }

        public static boolean isWhitespace(int c) {
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

        public interface SpaceCharFilter {
            public boolean isSpaceChar(int ch);
        }
    }
    static class IOUtils {
        public static void readIntArrays(InputReader in, int[]... arrays) {
            for (int i = 0; i < arrays[0].length; i++) {
                for (int j = 0; j < arrays.length; j++) {
                    arrays[j][i] = in.readInt();
                }
            }
        }
    }
    static class OutputWriter {
        private final PrintWriter writer;

        public OutputWriter(OutputStream outputStream) {
            writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
        }

        public OutputWriter(Writer writer) {
            this.writer = new PrintWriter(writer);
        }

        public void close() {
            writer.close();
        }

        public void printLine(int i) {
            writer.println(i);
        }
    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.PriorityQueue;
import java.util.StringTokenizer;

public class D {

	static boolean[][] grid;
	static long[][] weight;
	static int[] xx = { 0, 0, 1, -1 };
	static int[] yy = { 1, -1, 0, 0 };

	static class Position implements Comparable<Position> {
		int x, y, lit[];
		long w;

		Position(int x, int y, long w, int rowLit, int colLit) {
			this.x = x;
			this.y = y;
			this.w = w;
			lit = new int[] { rowLit, colLit };
		}

		@Override
		public int compareTo(Position o) {
			return Long.signum(
					w - o.w)  + grid.length - x + grid[0].length - y ;
		}

		public String toString() {
			return x + " : " + y + " : " + w;
		}

	}

	public static void main(String[] args) {
		Reader.init(System.in);
		try {
			final int n = Reader.nextInt();
			final int m = Reader.nextInt();
			final int k = Reader.nextInt();
			grid = new boolean[n][m];
			weight = new long[n][m];

			for (int i = 0; i < n; i++)
				Arrays.fill(weight[i], Long.MAX_VALUE);

			weight[0][0] = 0;

			for (int i = 0; i < k; i++)
				grid[Reader.nextInt() - 1][Reader.nextInt() - 1] = true;

			long minW = Long.MAX_VALUE;

			PriorityQueue<Position> q = new PriorityQueue<>();
			q.add(new Position(0, 0, 0, -1, -1));
			while (!q.isEmpty()) {
				Position pos = q.poll();
				if (pos.x == n - 1 && pos.y == m - 1) {
					minW = Math.min(minW, pos.w);
					continue;
				}

				for (int i = 0; i < 4; i++) {
					int nx = pos.x + xx[i];
					int ny = pos.y + yy[i];
					// if its out of bounds then skip this possibility
					if (nx >= n || nx < 0 || ny >= m || ny < 0)
						continue;

					// if its lit then add it without change
					if (grid[nx][ny] || nx == pos.lit[0] || ny == pos.lit[1]) {
						if (pos.w < weight[nx][ny]) {
							q.add(new Position(nx, ny, pos.w, pos.lit[0], pos.lit[1]));
							weight[nx][ny] = pos.w;
						}
					} else if (grid[pos.x][pos.y]) {
						if (pos.w + 1 <= weight[nx][ny]) {
							q.add(new Position(nx, ny, pos.w + 1, nx, -1));
							q.add(new Position(nx, ny, pos.w + 1, -1, ny));
							weight[nx][ny] = pos.w + 1;
						}
					}
				}

			}

			System.out.println((minW == Long.MAX_VALUE) ? -1 : minW);

		} catch (Exception e) {
		}

	}

	private static class Reader {
		static BufferedReader reader;
		static StringTokenizer tokenizer;

		static void init(InputStream input) {
			reader = new BufferedReader(new InputStreamReader(input));
			tokenizer = new StringTokenizer("");
		}

		static String next() throws IOException {
			while (!tokenizer.hasMoreTokens()) {
				// TODO add check for eof if necessary
				tokenizer = new StringTokenizer(reader.readLine());
			}
			return tokenizer.nextToken();
		}

		static long nextLong() throws IOException {
			return Long.parseLong(next());
		}

		static int nextInt() throws IOException {
			return Integer.parseInt(next());
		}

		static double nextDouble() throws IOException {
			return Double.parseDouble(next());
		}
	}

}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.PriorityQueue;
import java.util.StringTokenizer;

public class D {

	static boolean[][] grid;
	static long[][] weight;
	static int[] xx = { 0, 0, 1, -1 };
	static int[] yy = { 1, -1, 0, 0 };

	static class Position implements Comparable<Position> {
		int x, y;
		long w;

		Position(int x, int y, long w) {
			this.x = x;
			this.y = y;
			this.w = w;
		}

		@Override
		public int compareTo(Position o) {
			return Long.signum(w - o.w);
			// if (Long.signum(w - o.w) != 0)
			// return Long.signum(w - o.w);
			// return Integer.signum(o.x - x + o.y - y);
		}

		public String toString() {
			return x + " : " + y + " : " + w;
		}

	}

	public static void main(String[] args) {
		Reader.init(System.in);
		try {
			final int n = Reader.nextInt();
			final int m = Reader.nextInt();
			final int k = Reader.nextInt();
			grid = new boolean[n][m];
			weight = new long[n][m];

			for (int i = 0; i < n; i++)
				Arrays.fill(weight[i], Long.MAX_VALUE);

			weight[0][0] = 0;

			for (int i = 0; i < k; i++)
				grid[Reader.nextInt() - 1][Reader.nextInt() - 1] = true;

			long minW = Long.MAX_VALUE;

			PriorityQueue<Position> q = new PriorityQueue<>();
			q.add(new Position(0, 0, 0));
			while (!q.isEmpty()) {

				Position pos = q.poll();
				if (pos.x == n - 1 && pos.y == m - 1) {
					minW = Math.min(minW, pos.w);
					continue;
				}

				for (int i = 0; i < 4; i++) {
					int nx = pos.x + xx[i];
					int ny = pos.y + yy[i];
					// if its out of bounds then skip this possibility
					if (nx >= n || nx < 0 || ny >= m || ny < 0)
						continue;

					// if its lit then add it without change
					if (grid[nx][ny]) {
						if (pos.w < weight[nx][ny]) {
							q.add(new Position(nx, ny, pos.w));
							weight[nx][ny] = pos.w;
						}
						// otherwise if it can be lit
					} else if (grid[pos.x][pos.y]) {
						for (int x = 0; x < n; x++)
							if (pos.w + 1 < weight[x][ny]) {
								q.add(new Position(x, ny, pos.w + 1));
								weight[nx][ny] = pos.w + 1;
							}
						for (int y = 0; y < m; y++)
							if (pos.w + 1 < weight[nx][y]) {
								q.add(new Position(nx, y, pos.w + 1));
								weight[nx][ny] = pos.w + 1;
							}
					}
				}

			}

			System.out.println((minW == Long.MAX_VALUE) ? -1 : minW);

		} catch (Exception e) {
		}

	}

	private static class Reader {
		static BufferedReader reader;
		static StringTokenizer tokenizer;

		static void init(InputStream input) {
			reader = new BufferedReader(new InputStreamReader(input));
			tokenizer = new StringTokenizer("");
		}

		static String next() throws IOException {
			while (!tokenizer.hasMoreTokens()) {
				// TODO add check for eof if necessary
				tokenizer = new StringTokenizer(reader.readLine());
			}
			return tokenizer.nextToken();
		}

		static long nextLong() throws IOException {
			return Long.parseLong(next());
		}

		static int nextInt() throws IOException {
			return Integer.parseInt(next());
		}

		static double nextDouble() throws IOException {
			return Double.parseDouble(next());
		}
	}

}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.PriorityQueue;
import java.util.StringTokenizer;

public class D {

	static int[] xx = { 0, 0, 1, -1 };
	static int[] yy = { 1, -1, 0, 0 };

	static class Position implements Comparable<Position> {
		int x, y;
		long w;

		Position(int x, int y, long w) {
			this.x = x;
			this.y = y;
			this.w = w;
		}

		@Override
		public int compareTo(Position o) {
			return Long.signum(w - o.w);
			// if (Long.signum(w - o.w) != 0)
			// return Long.signum(w - o.w);
			// return Integer.signum(o.x - x + o.y - y);
		}

		public String toString() {
			return x + " : " + y + " : " + w;
		}

	}

	public static void main(String[] args) {
		Reader.init(System.in);
		try {
			final int n = Reader.nextInt();
			final int m = Reader.nextInt();
			final int k = Reader.nextInt();
			boolean[][] grid = new boolean[n][m];
			long[][] weight = new long[n][m];

			for (int i = 0; i < n; i++)
				Arrays.fill(weight[i], Long.MAX_VALUE);

			weight[0][0] = 0;

			for (int i = 0; i < k; i++)
				grid[Reader.nextInt() - 1][Reader.nextInt() - 1] = true;

			long minW = Long.MAX_VALUE;

			PriorityQueue<Position> q = new PriorityQueue<>();
			q.add(new Position(0, 0, 0));
			while (!q.isEmpty()) {

				Position pos = q.poll();
				if (pos.x == n - 1 && pos.y == m - 1) {
					minW = Math.min(minW, pos.w);
					continue;
				}

				for (int i = 0; i < 4; i++) {
					int nx = pos.x + xx[i];
					int ny = pos.y + yy[i];
					// if its out of bounds then skip this possibility
					if (nx >= n || nx < 0 || ny >= m || ny < 0)
						continue;

					// if its lit then add it without change
					if (grid[nx][ny]) {
						if (pos.w < weight[nx][ny]) {
							q.add(new Position(nx, ny, pos.w));
							weight[nx][ny] = pos.w;
						}
						// otherwise if it can be lit
					} else if (grid[pos.x][pos.y]) {
						for (int x = 0; x < n; x++)
							if (pos.w + 1 < weight[x][ny]) {
								q.add(new Position(x, ny, pos.w + 1));
								weight[nx][ny] = pos.w + 1;
							}
						for (int y = 0; y < m; y++)
							if (pos.w + 1 < weight[nx][y]) {
								q.add(new Position(nx, y, pos.w + 1));
								weight[nx][ny] = pos.w + 1;
							}
					}
				}

			}

			System.out.println((minW == Long.MAX_VALUE) ? -1 : minW);

		} catch (Exception e) {
		}

	}

	private static class Reader {
		static BufferedReader reader;
		static StringTokenizer tokenizer;

		static void init(InputStream input) {
			reader = new BufferedReader(new InputStreamReader(input));
			tokenizer = new StringTokenizer("");
		}

		static String next() throws IOException {
			while (!tokenizer.hasMoreTokens()) {
				// TODO add check for eof if necessary
				tokenizer = new StringTokenizer(reader.readLine());
			}
			return tokenizer.nextToken();
		}

		static long nextLong() throws IOException {
			return Long.parseLong(next());
		}

		static int nextInt() throws IOException {
			return Integer.parseInt(next());
		}

		static double nextDouble() throws IOException {
			return Double.parseDouble(next());
		}
	}

}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Set;
import java.util.StringTokenizer;

public class D {

	private static class Reader {
		static BufferedReader reader;
		static StringTokenizer tokenizer;

		static void init(InputStream input) {
			reader = new BufferedReader(new InputStreamReader(input));
			tokenizer = new StringTokenizer("");
		}

		static String next() throws IOException {
			while (!tokenizer.hasMoreTokens()) {
				// TODO add check for eof if necessary
				tokenizer = new StringTokenizer(reader.readLine());
			}
			return tokenizer.nextToken();
		}

		static long nextLong() throws IOException {
			return Long.parseLong(next());
		}

		static int nextInt() throws IOException {
			return Integer.parseInt(next());
		}

		static double nextDouble() throws IOException {
			return Double.parseDouble(next());
		}
	}

	static int[] xx = { 0, 0, 1, -1 };
	static int[] yy = { 1, -1, 0, 0 };

	static class Pair {
		final int x, y;

		Pair(int a, int b) {
			x = a;
			y = b;
		}

		@Override
		public boolean equals(Object o) {
			return ((Pair) o).x == x && ((Pair) o).y == y;
		}

		public String toString() {
			return "[" + x + " : " + y + "]";
		}

		@Override
		public int hashCode() {
			return x * (y / 10 + 1) + y;
		}

	}

	static class Position implements Comparable<Position> {
		Pair p;
		int w;

		Position(Pair p, int w) {
			this.p = p;
			this.w = w;
		}

		int x() {
			return p.x;
		}

		int y() {
			return p.y;
		}

		@Override
		public int compareTo(Position o) {
			return Integer.signum(w - o.w);
		}

		public String toString() {
			return x() + " : " + y() + " : " + w;
		}

	}

	public static void main(String[] args) {
		Reader.init(System.in);

		try {

			final int n = Reader.nextInt();
			final int m = Reader.nextInt();
			final int k = Reader.nextInt();
			final Pair END = new Pair(n - 1, m - 1);
			Map<Pair, Integer> w = new HashMap<>();
			Set<Pair>[] rows = new Set[n + 1];
			Set<Pair>[] cols = new Set[m + 1];

			for (int i = 0; i < n + 1; i++)
				rows[i] = new HashSet<>();
			for (int i = 0; i < m + 1; i++)
				cols[i] = new HashSet<>();

			for (int i = 0; i < k; i++) {
				int x = Reader.nextInt() - 1;
				int y = Reader.nextInt() - 1;
				Pair pii = new Pair(x, y);
				Position p = new Position(pii, Integer.MAX_VALUE);
				rows[x].add(pii);
				cols[y].add(pii);
				w.put(pii, Integer.MAX_VALUE);
			}

			int minW = Integer.MAX_VALUE;

			PriorityQueue<Position> q = new PriorityQueue<>();
			q.add(new Position(new Pair(0, 0), 0));
			w.put(new Pair(0, 0), 0);

			while (!q.isEmpty()) {
				Position pos = q.poll();

				if (pos.p.equals(END)) {
					minW = Math.min(minW, pos.w);
					break;
				}
				if ((pos.x() - 2 < END.x && END.x < pos.x() + 2) || (pos.y() - 2 < END.y && END.y < pos.y() + 2))
					q.add(new Position(END, pos.w + 1));

				// for all adjacent positions
				for (int i = 0; i < 4; i++) {
					int nx = pos.x() + xx[i];
					int ny = pos.y() + yy[i];
					Pair p = new Pair(nx, ny);
					// if it is present then this is the fastest path to it
					if (nx >= 0 && nx <= n && ny >= 0 && ny <= m) {
						if (rows[nx].remove(p)) {
							cols[ny].remove(p);
							w.put(p, pos.w);
							q.add(new Position(p, pos.w));
						}
					}
				}

				for (int x = pos.x() - 2; x <= pos.x() + 2; x++)
					if (x >= 0 && x <= n)
						for (Pair y : rows[x])
							if (pos.w + 1 < w.get(y)) {
								Position p = new Position(y, pos.w + 1);
								q.add(p);
								w.put(y, pos.w + 1);
							}

				for (int y = pos.y() - 2; y <= pos.y() + 2; y++)
					if (y >= 0 && y <= m)
						for (Pair x : cols[y])
							if (pos.w + 1 < w.get(x)) {
								Position p = new Position(x, pos.w + 1);
								q.add(p);
								w.put(x, pos.w + 1);
							}
			}

			System.out.println((minW == Integer.MAX_VALUE) ? -1 : minW);

		} catch (

		Exception e) {
			e.printStackTrace();
		}

	}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.PriorityQueue;
import java.util.StringTokenizer;

public class D {

	static int[] xx = { 0, 0, 1, -1 };
	static int[] yy = { 1, -1, 0, 0 };

	static class Position implements Comparable<Position> {
		int x, y;
		int w;

		Position(int x, int y, int w) {
			this.x = x;
			this.y = y;
			this.w = w;
		}

		@Override
		public int compareTo(Position o) {
			return Integer.signum(w - o.w);
			// if (Long.signum(w - o.w) != 0)
			// return Long.signum(w - o.w);
			// return Integer.signum(o.x - x + o.y - y);
		}

		public String toString() {
			return x + " : " + y + " : " + w;
		}

	}

	public static void main(String[] args) {
		Reader.init(System.in);
		try {
			final int n = Reader.nextInt();
			final int m = Reader.nextInt();
			final int k = Reader.nextInt();
			boolean[][] grid = new boolean[n][m];
			int[][] weight = new int[n][m];

			for (int i = 0; i < n; i++)
				Arrays.fill(weight[i], Integer.MAX_VALUE);

			weight[0][0] = 0;

			for (int i = 0; i < k; i++)
				grid[Reader.nextInt() - 1][Reader.nextInt() - 1] = true;

			int minW = Integer.MAX_VALUE;

			PriorityQueue<Position> q = new PriorityQueue<>();
			q.add(new Position(0, 0, 0));
			while (!q.isEmpty()) {

				Position pos = q.poll();
				if (pos.x == n - 1 && pos.y == m - 1) {
					minW = Math.min(minW, pos.w);
					continue;
				}

				for (int i = 0; i < 4; i++) {
					int nx = pos.x + xx[i];
					int ny = pos.y + yy[i];
					// if its out of bounds then skip this possibility
					if (nx >= n || nx < 0 || ny >= m || ny < 0)
						continue;

					// if its lit then add it without change
					if (grid[nx][ny]) {
						if (pos.w < weight[nx][ny]) {
							q.add(new Position(nx, ny, pos.w));
							weight[nx][ny] = pos.w;
						}
						// otherwise if it can be lit
					} else if (grid[pos.x][pos.y]) {
						for (int x = 0; x < n; x++)
							if (pos.w + 1 < weight[x][ny]) {
								q.add(new Position(x, ny, pos.w + 1));
								weight[nx][ny] = pos.w + 1;
							}
						for (int y = 0; y < m; y++)
							if (pos.w + 1 < weight[nx][y]) {
								q.add(new Position(nx, y, pos.w + 1));
								weight[nx][ny] = pos.w + 1;
							}
					}
				}

			}

			System.out.println((minW == Integer.MAX_VALUE) ? -1 : minW);

		} catch (Exception e) {
		}

	}

	private static class Reader {
		static BufferedReader reader;
		static StringTokenizer tokenizer;

		static void init(InputStream input) {
			reader = new BufferedReader(new InputStreamReader(input));
			tokenizer = new StringTokenizer("");
		}

		static String next() throws IOException {
			while (!tokenizer.hasMoreTokens()) {
				// TODO add check for eof if necessary
				tokenizer = new StringTokenizer(reader.readLine());
			}
			return tokenizer.nextToken();
		}

		static long nextLong() throws IOException {
			return Long.parseLong(next());
		}

		static int nextInt() throws IOException {
			return Integer.parseInt(next());
		}

		static double nextDouble() throws IOException {
			return Double.parseDouble(next());
		}
	}

}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.PriorityQueue;
import java.util.StringTokenizer;

public class D {

	static boolean[][] grid;
	static long[][] weight;
	static int[] xx = { 0, 0, 1, -1 };
	static int[] yy = { 1, -1, 0, 0 };

	static class Position implements Comparable<Position> {
		int x, y, lit[];
		long w;

		Position(int x, int y, long w, int rowLit, int colLit) {
			this.x = x;
			this.y = y;
			this.w = w;
			lit = new int[] { rowLit, colLit };
		}

		@Override
		public int compareTo(Position o) {
			return Long.signum(
					w - o.w)  + grid.length - x + grid[0].length - y ;
		}

		public String toString() {
			return x + " : " + y + " : " + w;
		}

	}

	public static void main(String[] args) {
		Reader.init(System.in);
		try {
			final int n = Reader.nextInt();
			final int m = Reader.nextInt();
			final int k = Reader.nextInt();
			grid = new boolean[n][m];
			weight = new long[n][m];

			for (int i = 0; i < n; i++)
				Arrays.fill(weight[i], Long.MAX_VALUE);

			weight[0][0] = 0;

			for (int i = 0; i < k; i++)
				grid[Reader.nextInt() - 1][Reader.nextInt() - 1] = true;

			long minW = Long.MAX_VALUE;

			PriorityQueue<Position> q = new PriorityQueue<>();
			q.add(new Position(0, 0, 0, -1, -1));
			while (!q.isEmpty()) {
				Position pos = q.poll();
				if (pos.x == n - 1 && pos.y == m - 1) {
					minW = Math.min(minW, pos.w);
					continue;
				}

				for (int i = 0; i < 4; i++) {
					int nx = pos.x + xx[i];
					int ny = pos.y + yy[i];
					// if its out of bounds then skip this possibility
					if (nx >= n || nx < 0 || ny >= m || ny < 0)
						continue;

					// if its lit then add it without change
					if (grid[nx][ny] || nx == pos.lit[0] || ny == pos.lit[1]) {
						if (pos.w < weight[nx][ny]) {
							q.add(new Position(nx, ny, pos.w, pos.lit[0], pos.lit[1]));
							weight[nx][ny] = pos.w;
						}
					} else if (grid[pos.x][pos.y]) {
						if (pos.w + 1 < weight[nx][ny]) {
							q.add(new Position(nx, ny, pos.w + 1, nx, -1));
							q.add(new Position(nx, ny, pos.w + 1, -1, ny));
							weight[nx][ny] = pos.w + 1;
						}
					}
				}

			}

			System.out.println((minW == Long.MAX_VALUE) ? -1 : minW);

		} catch (Exception e) {
		}

	}

	private static class Reader {
		static BufferedReader reader;
		static StringTokenizer tokenizer;

		static void init(InputStream input) {
			reader = new BufferedReader(new InputStreamReader(input));
			tokenizer = new StringTokenizer("");
		}

		static String next() throws IOException {
			while (!tokenizer.hasMoreTokens()) {
				// TODO add check for eof if necessary
				tokenizer = new StringTokenizer(reader.readLine());
			}
			return tokenizer.nextToken();
		}

		static long nextLong() throws IOException {
			return Long.parseLong(next());
		}

		static int nextInt() throws IOException {
			return Integer.parseInt(next());
		}

		static double nextDouble() throws IOException {
			return Double.parseDouble(next());
		}
	}

}


import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.StringTokenizer;

public class d
{
	/*
	 	0 - col before lit
	 	1 - cur col lit
	 	2 - cur row lit
	 */
	public static void main(String[] args)
	{
		FastScanner in = new FastScanner();
		int n = in.nextInt();
		int m = in.nextInt();
		int k = in.nextInt();
		ArrayList<Point> rows[] = new ArrayList[n+1];
		ArrayList<Point> cols[] = new ArrayList[m];
		Point points[] = new Point[k+1];

		for(int i = 0; i < n; i++)
			rows[i] = new ArrayList<>();
		for(int i = 0; i < m; i++)
			cols[i] = new ArrayList<>();

		Point dest = null, start = null;

		for(int i = 0; i < k; i++)
		{
			int r = in.nextInt()-1;
			int c = in.nextInt()-1;
			Point p = new Point(r, c);

			if(r == 0 && c == 0)
				start = p;
			else
			{
				if(r == n-1 && c == m-1)
					dest = p;

				rows[r].add(p);
				cols[c].add(p);
				points[i] = p;
			}
		}

		if(dest == null)
		{
			dest = points[k] = new Point(n-1, m-1);
			rows[n-1].add(dest);
			cols[m-1].add(dest);
		}
		ArrayDeque<State> q = new ArrayDeque<>();
		q.add(new State(0, 0, 0, 0, start));

		while(!q.isEmpty())
		{
			State cur = q.pollFirst();
			if(cur.p.v[cur.status]) continue;
			cur.p.v[cur.status] = true;
//			System.out.println(cur.p + " " + cur.status + " " + cur.dist);

			for(Point next : rows[cur.r])
			{
				if(next == null) continue;
				if(Math.abs(cur.c - next.c) == 1 && !next.v[0] && next != points[k])
				{
					int nextDist = cur.dist;
					if(nextDist < next.dist[0])
					{
//						System.out.println("Next to in same row");
						next.dist[0] = nextDist;
						q.addFirst(new State(next.r, next.c, nextDist, 0, next));
					}
				}
				else if(!next.v[2])
				{
					int nextDist = cur.dist + (cur.status == 2 ? 0 : 1);;
					if(nextDist < next.dist[2])
					{
//						System.out.println("Same row " + (cur.status == 2));
						next.dist[2] = nextDist;

						if(cur.status == 2)
							q.addFirst(new State(next.r, next.c, next.dist[2], 2, next));
						else
							q.addLast(new State(next.r, next.c, next.dist[2], 2, next));
					}
				}
			}

			for(Point next : cols[cur.c])
			{
				if(next == null) continue;
				if(Math.abs(cur.r - next.r) == 1 && !next.v[0] && next != points[k])
				{
//					next.v[0] = true;

					int nextDist = cur.dist;
					if(nextDist < next.dist[0])
					{
//						System.out.println("Next to in same col");
						next.dist[0] = nextDist;
						q.addFirst(new State(next.r, next.c, next.dist[0], 0, next));
					}
				}
				else if(!next.v[1])
				{
					int nextDist = cur.dist + (cur.status == 1 ? 0 : 1);

					if(nextDist < next.dist[1])
					{
//						System.out.println("Same col " + (cur.status == 1));
						next.dist[1] = nextDist;
						if(cur.status == 1)
							q.addFirst(new State(next.r, next.c, next.dist[1], 1, next));
						else
							q.addLast(new State(next.r, next.c, next.dist[1], 1, next));
					}
				}
			}

			if(cur.r+1 < n) for(Point next : rows[cur.r+1])
			{
				if(next == null) continue;
//				if(next == points[k]) continue;

				int nextDist = cur.dist + (cur.status == 2 && next != points[k] ? 0 : 1);
				int nextS = cur.status == 2 && next != points[k] ? 0 : 2;
				if(next.v[nextS]) continue;
				if(nextDist < next.dist[nextS])
				{
//					System.out.println("Next row " + (cur.status == 2) + " " + next);
					next.dist[nextS] = nextDist;

					if(cur.status == 2 && next != points[k])
						q.addFirst(new State(next.r, next.c, next.dist[nextS], nextS, next));
					else
						q.addLast(new State(next.r, next.c, next.dist[nextS], nextS, next));
				}
			}

			if(cur.r-1 >= 0) for(Point next : rows[cur.r-1])
			{
				if(next == null) continue;
//				if(next == points[k]) continue;

				int nextDist = cur.dist + (cur.status == 2 && next != points[k] ? 0 : 1);
				int nextS = cur.status == 2 && next != points[k] ? 0 : 2;
				if(nextDist < next.dist[nextS])
				{
//					System.out.println("Prev row " + (cur.status == 2) + " " + next);
					next.dist[nextS] = nextDist;

					if(cur.status == 2 && next != points[k])
						q.addFirst(new State(next.r, next.c, next.dist[nextS], nextS, next));
					else
						q.addLast(new State(next.r, next.c, next.dist[nextS], nextS, next));
				}
			}

			if(cur.c+1 < m) for(Point next : cols[cur.c+1])
			{
				if(next == null) continue;
				if(next.v[0]) continue;
//				if(next == points[k]) continue;

				int nextDist = cur.dist + (cur.status == 1 && next != points[k] ? 0 : 1);
				int nextS = cur.status == 1 && next != points[k] ? 0 : 1;
				if(nextDist < next.dist[nextS])
				{
//					System.out.println("Next col" + (cur.status == 1));
					next.dist[nextS] = nextDist;

					if(cur.status == 1 && next != points[k])
						q.addFirst(new State(next.r, next.c, next.dist[nextS], nextS, next));
					else
						q.addLast(new State(next.r, next.c, next.dist[nextS], nextS, next));
				}
			}

			if(cur.c-1 >= 0) for(Point next : cols[cur.c-1])
			{
				if(next == null) continue;
//				if(next == points[k]) continue;

				int nextDist = cur.dist + (cur.status == 1 && next != points[k] ? 0 : 1);
				int nextS = cur.status == 1 && next != points[k] ? 0 : 1;
				if(next.v[nextS]) continue;
				if(nextDist < next.dist[nextS])
				{
//					System.out.println("Prev col" + (cur.status == 1));
					next.dist[nextS] = nextDist;

					if(cur.status == 1 && next != points[k])
						q.addFirst(new State(next.r, next.c, next.dist[nextS], nextS, next));
					else
						q.addLast(new State(next.r, next.c, next.dist[nextS], nextS, next));
				}
			}

			if(cur.r+2 < n) for(Point next : rows[cur.r+2])
			{
				if(next == null) continue;
				if(next.v[0]) continue;
				if(next == points[k]) continue;

				int nextDist = cur.dist + 1;
				int nextS = 0;
				if(nextDist < next.dist[nextS])
				{
//					System.out.println("Next row2 " + (cur.status == 2) + " " + next);
					next.dist[nextS] = nextDist;
					q.addLast(new State(next.r, next.c, next.dist[nextS], nextS, next));
				}
			}

			if(cur.c+2 < m) for(Point next : cols[cur.c+2])
			{
				if(next == null) continue;
				if(next.v[0]) continue;
				if(next == points[k]) continue;

				int nextDist = cur.dist + 1;
				int nextS = 0;
				if(nextDist < next.dist[nextS])
				{
//					System.out.println("Next2 col" + (cur.status == 1));
					next.dist[nextS] = nextDist;
					q.addLast(new State(next.r, next.c, next.dist[nextS], nextS, next));
				}
			}

			if(cur.r-2 >= 0) for(Point next : rows[cur.r-2])
			{
				if(next == null) continue;
				if(next.v[0]) continue;
				if(next == points[k]) continue;

				int nextDist = cur.dist + 1;
				int nextS = 0;
				if(nextDist < next.dist[nextS])
				{
//					System.out.println("Prev2 row " + (cur.status == 2) + " " + next);
					next.dist[nextS] = nextDist;
					q.addLast(new State(next.r, next.c, next.dist[nextS], nextS, next));
				}
			}

			if(cur.c-2 >= 0) for(Point next : cols[cur.c-2])
			{
				if(next == null) continue;
				if(next.v[0]) continue;
				if(next == points[k]) continue;

				int nextDist = cur.dist + 1;
				int nextS = 0;
				if(nextDist < next.dist[nextS])
				{
//					System.out.println("Prev2 col" + (cur.status == 1));
					next.dist[nextS] = nextDist;
					q.addLast(new State(next.r, next.c, next.dist[nextS], nextS, next));
				}
			}
		}

//		for(int i = 0; i <= k; i++)
//			System.out.println(points[i]);

		int ans = Math.min(Math.min(dest.dist[0], dest.dist[1]), dest.dist[2]);
		if(ans == Integer.MAX_VALUE)
			System.out.println(-1);
		else
			System.out.println(ans);
	}

	public static class State
	{
		int dist, r, c, status;
		Point p;

		public State(int rr, int cc, int d, int s, Point pp)
		{
			dist = d;
			r = rr;
			c = cc;
			status = s;
			p = pp;
		}
	}

	public static class Point
	{
		int r, c;
		boolean v[];
		int dist[];

		public Point(int xx, int yy)
		{
			r = xx;
			c = yy;
			dist = new int[3];
			v = new boolean[3];

			Arrays.fill(dist, Integer.MAX_VALUE);
		}

		public String toString()
		{
			return (r+1) + " " + (c+1) + " " + Arrays.toString(dist) + " " + Arrays.toString(v);
		}
	}

	public static class FastScanner
	{
		BufferedReader br;
		StringTokenizer st;

		public FastScanner(String s)
		{
			try {
				br = new BufferedReader(new FileReader(s));
			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		public FastScanner()
		{
			br = new BufferedReader(new InputStreamReader(System.in));
		}

		String nextToken()
		{
			while (st == null || !st.hasMoreElements())
			{
				try {
					st = new StringTokenizer(br.readLine());
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			return st.nextToken();
		}

		int nextInt()
		{
			return Integer.parseInt(nextToken());
		}

		long nextLong()
		{
			return Long.parseLong(nextToken());
		}

		double nextDouble()
		{
			return Double.parseDouble(nextToken());
		}

		String next()
		{
			return nextToken();
		}
	}
}


//package round420;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Deque;
import java.util.InputMismatchException;

public class D2 {
	InputStream is;
	PrintWriter out;
	String INPUT = "";

	void solve()
	{
		int n = ni(), m = ni(), K = ni();
		int[][] co = new int[K][];
		boolean end = false;
		for(int i = 0;i < K;i++){
			co[i] = new int[]{ni(), ni()};
			if(co[i][0] == n && co[i][1] == m){
				end= true;
			}
		}
		if(!end){
			K++;
			co = Arrays.copyOf(co, K);
			co[K-1] = new int[]{n, m};
		}
		Arrays.sort(co, new Comparator<int[]>() {
			public int compare(int[] a, int[] b) {
				if(a[0] != b[0])return a[0] - b[0];
				return a[1] - b[1];
			}
		});

		Deque<Integer> q = new ArrayDeque<>();
		q.add(0);
		int[] ds = new int[K];
		Arrays.fill(ds, 99999999);
		ds[0] = 0;

		while(!q.isEmpty()){
			int cur = q.poll();
			for(int j = 0;j < K;j++){
				int dr = Math.abs(co[cur][0]-co[j][0]);
				int dc = Math.abs(co[cur][1]-co[j][1]);
				if(j == K-1 && !end){
					if(dr <= 1 || dc <= 1){
						if(ds[j] > ds[cur] + 1){
							ds[j] = ds[cur] + 1;
							q.addLast(j);
						}
					}
				}else{
					if(dr+dc <= 1){
						if(ds[j] > ds[cur]){
							ds[j] = ds[cur];
							q.addFirst(j);
						}
					}else if(dr <= 2 || dc <= 2){
						if(ds[j] > ds[cur] + 1){
							ds[j] = ds[cur] + 1;
							q.addLast(j);
						}
					}
				}
			}
		}
		if(ds[K-1] >= 999999){
			out.println(-1);
		}else{
			out.println(ds[K-1]);
		}
	}

	void run() throws Exception
	{
		is = oj ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);

		long s = System.currentTimeMillis();
		solve();
		out.flush();
		tr(System.currentTimeMillis()-s+"ms");
	}

	public static void main(String[] args) throws Exception { new D2().run(); }

	private byte[] inbuf = new byte[1024];
	public int lenbuf = 0, ptrbuf = 0;

	private int readByte()
	{
		if(lenbuf == -1)throw new InputMismatchException();
		if(ptrbuf >= lenbuf){
			ptrbuf = 0;
			try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); }
			if(lenbuf <= 0)return -1;
		}
		return inbuf[ptrbuf++];
	}

	private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); }
	private int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }

	private double nd() { return Double.parseDouble(ns()); }
	private char nc() { return (char)skip(); }

	private String ns()
	{
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while(!(isSpaceChar(b))){ // when nextLine, (isSpaceChar(b) && b != ' ')
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	private char[] ns(int n)
	{
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while(p < n && !(isSpaceChar(b))){
			buf[p++] = (char)b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}

	private char[][] nm(int n, int m)
	{
		char[][] map = new char[n][];
		for(int i = 0;i < n;i++)map[i] = ns(m);
		return map;
	}

	private int[] na(int n)
	{
		int[] a = new int[n];
		for(int i = 0;i < n;i++)a[i] = ni();
		return a;
	}

	private int ni()
	{
		int num = 0, b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private long nl()
	{
		long num = 0;
		int b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	private void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}


//package round420;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Deque;
import java.util.InputMismatchException;

public class D {
	InputStream is;
	PrintWriter out;
	String INPUT = "";

	void solve()
	{
		int n = ni(), m = ni(), K = ni();
		int[][] co = new int[K][];
		boolean end = false;
		for(int i = 0;i < K;i++){
			co[i] = new int[]{ni(), ni()};
			if(co[i][0] == n && co[i][1] == m){
				end= true;
			}
		}
		if(!end){
			K++;
			co = Arrays.copyOf(co, K);
			co[K-1] = new int[]{n, m};
		}
		Arrays.sort(co, new Comparator<int[]>() {
			public int compare(int[] a, int[] b) {
				if(a[0] != b[0])return a[0] - b[0];
				return a[1] - b[1];
			}
		});

		Deque<Integer> q = new ArrayDeque<>();
		q.add(0);
		int[] ds = new int[K];
		Arrays.fill(ds, 99999999);
		ds[0] = 0;

		while(!q.isEmpty()){
			int cur = q.poll();
			for(int j = 0;j < K;j++){
				int dr = Math.abs(co[cur][0]-co[j][0]);
				int dc = Math.abs(co[cur][1]-co[j][1]);
				if(j == K-1 && !end){
					if(dr <= 1 || dc <= 1){
						if(ds[j] > ds[cur] + 1){
							ds[j] = ds[cur] + 1;
							q.addLast(j);
						}
					}
				}else{
					if(dr+dc <= 1){
						if(ds[j] > ds[cur]){
							ds[j] = ds[cur];
							q.addFirst(j);
						}
					}else if(dr <= 1 || dc <= 1){
						if(ds[j] > ds[cur] + 1){
							ds[j] = ds[cur] + 1;
							q.addLast(j);
						}
					}
				}
			}
		}
		if(ds[K-1] >= 999999){
			out.println(-1);
		}else{
			out.println(ds[K-1]);
		}
	}

	void run() throws Exception
	{
		is = oj ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);

		long s = System.currentTimeMillis();
		solve();
		out.flush();
		tr(System.currentTimeMillis()-s+"ms");
	}

	public static void main(String[] args) throws Exception { new D().run(); }

	private byte[] inbuf = new byte[1024];
	public int lenbuf = 0, ptrbuf = 0;

	private int readByte()
	{
		if(lenbuf == -1)throw new InputMismatchException();
		if(ptrbuf >= lenbuf){
			ptrbuf = 0;
			try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); }
			if(lenbuf <= 0)return -1;
		}
		return inbuf[ptrbuf++];
	}

	private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); }
	private int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }

	private double nd() { return Double.parseDouble(ns()); }
	private char nc() { return (char)skip(); }

	private String ns()
	{
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while(!(isSpaceChar(b))){ // when nextLine, (isSpaceChar(b) && b != ' ')
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	private char[] ns(int n)
	{
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while(p < n && !(isSpaceChar(b))){
			buf[p++] = (char)b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}

	private char[][] nm(int n, int m)
	{
		char[][] map = new char[n][];
		for(int i = 0;i < n;i++)map[i] = ns(m);
		return map;
	}

	private int[] na(int n)
	{
		int[] a = new int[n];
		for(int i = 0;i < n;i++)a[i] = ni();
		return a;
	}

	private int ni()
	{
		int num = 0, b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private long nl()
	{
		long num = 0;
		int b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	private void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Div2_420D {

	public static void main(String[] args) throws IOException {
		new Div2_420D().execute();
	}

	@SuppressWarnings("unchecked")
	void execute() throws IOException {
		BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer inputData = new StringTokenizer(reader.readLine());
		int numR = Integer.parseInt(inputData.nextToken());
		int numC = Integer.parseInt(inputData.nextToken());
		int numM = Integer.parseInt(inputData.nextToken());

		ArrayList<Pair>[] rItems = new ArrayList[numR + 2];
		ArrayList<Pair>[] cItems = new ArrayList[numC + 2];

		for (int i = 0; i <= numR + 1; i++) {
			rItems[i] = new ArrayList<Pair>();
		}
		for (int i = 0; i <= numC + 1; i++) {
			cItems[i] = new ArrayList<Pair>();
		}

		Pair start = null;
		for (int i = 0; i < numM; i++) {
			inputData = new StringTokenizer(reader.readLine());
			int r = Integer.parseInt(inputData.nextToken());
			int c = Integer.parseInt(inputData.nextToken());
			Pair cPair = new Pair(r, c, i);
			if (r == 1 && c == 1) {
				start = cPair;
			}
			rItems[r].add(cPair);
			cItems[c].add(cPair);
		}

		int[] cost = new int[numM];
		Arrays.fill(cost, Integer.MAX_VALUE / 8);
		cost[start.id] = 0;

		boolean[] proc = new boolean[numM];

		ArrayDeque<Pair> bfsQueue = new ArrayDeque<Pair>();
		bfsQueue.add(start);

		while (!bfsQueue.isEmpty()) {
			Pair cur = bfsQueue.remove();
			int cCost = cost[cur.id];

			if (cur.r == numR && cur.c == numC) {
				System.out.println(cCost);
				return;
			}
			if (proc[cur.id]) {
				continue;
			}
			proc[cur.id] = true;

			for (int rDel = -2; rDel <= 2; rDel++) {
				if (cur.r + rDel < 1 || cur.r + rDel > numR) {
					continue;
				}
				for (Pair rPeer : rItems[cur.r + rDel]) {
					if (Math.abs(rPeer.r - cur.r) + Math.abs(rPeer.c - cur.c) == 1) {
						if (cost[rPeer.id] > cCost) {
							cost[rPeer.id] = cCost;
							bfsQueue.addFirst(rPeer);
						}
					} else {
						if (cost[rPeer.id] > cCost + 1) {
							cost[rPeer.id] = cCost + 1;
							bfsQueue.addLast(rPeer);
						}
					}
				}
			}

			for (int cDel = -2; cDel <= 2; cDel++) {
				if (cur.c + cDel < 1 || cur.c + cDel > numC) {
					continue;
				}
				for (Pair cPeer : cItems[cur.c + cDel]) {
					if (Math.abs(cPeer.r - cur.r) + Math.abs(cPeer.c - cur.c) == 1) {
						if (cost[cPeer.id] > cCost) {
							cost[cPeer.id] = cCost;
							bfsQueue.addFirst(cPeer);
						}
					} else {
						if (cost[cPeer.id] > cCost + 1) {
							cost[cPeer.id] = cCost + 1;
							bfsQueue.addLast(cPeer);
						}
					}
				}
			}
		}

		int ans = Integer.MAX_VALUE / 8;

		for (Pair cPair : rItems[numR]) {
			if (cost[cPair.id] + 1 < ans) {
				ans = cost[cPair.id] + 1;
			}
		}
		for (Pair cPair : rItems[numR - 1]) {
			if (cost[cPair.id] + 1 < ans) {
				ans = cost[cPair.id] + 1;
			}
		}
		for (Pair cPair : cItems[numC]) {
			if (cost[cPair.id] + 1 < ans) {
				ans = cost[cPair.id] + 1;
			}
		}
		for (Pair cPair : cItems[numC - 1]) {
			if (cost[cPair.id] + 1 < ans) {
				ans = cost[cPair.id] + 1;
			}
		}
		if (ans < Integer.MAX_VALUE / 8) {
			System.out.println(ans);
			return;
		}

		System.out.println(-1);
	}

	class Pair {
		int r;
		int c;
		int id;

		Pair(int r, int c, int id) {
			this.r = r;
			this.c = c;
			this.id = id;
		}
	}
}


//package codeforces;

import java.io.*;
import java.util.Arrays;
import java.util.Formatter;
import java.util.StringTokenizer;

/**
 * Created by nitin.s on 03/08/17.
 */

public class OkabeAndCity {
    static class FastReader {
        BufferedReader br;
        StringTokenizer tk;

        FastReader(InputStreamReader ir) {
            br = new BufferedReader(ir);
        }

        String next() {
            while ((tk == null) || (!tk.hasMoreElements())) {
                tk = new StringTokenizer(nextLine());
            }
            return tk.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        long nextLong() {
            return Long.parseLong(next());
        }

        String nextLine() {
            try {
                return br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
        }

    }

    static class FastWriter {
        BufferedWriter out;
        Formatter frm;

        FastWriter(OutputStreamWriter writer) {
            out = new BufferedWriter(writer);
            frm = new Formatter(out);
        }

        FastWriter printf(String format, Object... args) {
            frm.format(format, args).flush();
            return this;
        }

        FastWriter print(String str) {
            try {
                out.write(str);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return this;
        }

        FastWriter print(int x) {
            return print(Integer.toString(x));
        }

        FastWriter print(long x) {
            return print(Long.toString(x));
        }

        FastWriter print(double x) {
            return print(Double.toString(x));
        }

        FastWriter print(float x) {
            return print(Float.toString(x));
        }

        FastWriter print(short x) {
            return print(Short.toString(x));
        }

        FastWriter print(char c) {
            try {
                out.write(c);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return this;
        }

        FastWriter print(Object x) {
            return print(x.toString());
        }

        FastWriter println() {
            try {
                out.newLine();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return this;
        }

        FastWriter println(String str) {
            return print(str).println();
        }

        FastWriter println(long x) {
            return print(x).println();
        }

        FastWriter println(int x) {
            return print(x).println();
        }

        FastWriter println(double x) {
            return print(x).println();
        }

        FastWriter println(char x) {
            return print(x).println();
        }

        FastWriter println(float x) {
            return print(x).println();
        }

        FastWriter println(short x) {
            return print(x).println();
        }

        FastWriter println(Object x) {
            return print(x).println();
        }

        public void close() {
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    public static void main(String[] args) {
        new Solver(new FastReader(new InputStreamReader(System.in)), new FastWriter(new OutputStreamWriter(System.out)));
    }
}

class Solver {
    OkabeAndCity.FastReader in;
    OkabeAndCity.FastWriter out;

    void main() {
        int n = in.nextInt(), m = in.nextInt(), kk = in.nextInt();
        int[] x = new int[kk + 1], y = new int[kk + 1];
        int INF = kk * 11;
        boolean last = false;
        x[0] = y[0] = 1;
        int k = 1;
        for (int i = 0; i < kk; i++) {
            x[k] = in.nextInt();
            y[k] = in.nextInt();
            if ((x[i] != 1) || (y[i] != 1)) {
                k++;
            }
        }
        int[] f = new int[k + 2];
        f[k] = INF;
        Arrays.fill(f, INF);
        boolean[] w = new boolean[k + 1];
        Arrays.fill(w, false);
        int ans = INF;
        f[0] = 0;
        for (;;) {
            int v = k;
            for (int i = 0; i < k; i++) {
                if (!w[i] && f[i] < f[v]) {
                    v = i;
                }
            }
            if (v == k) break;
            w[v] = true;
            if ((x[v] == n) && (y[v] == m)) {
                ans = Math.min(ans, f[v]);
            }

            if ((x[v] >= n - 1) || (y[v] >= m - 1)) {
                ans = Math.min(ans, f[v] + 1);
            }

            for (int i = 0; i < k; i++) {
                if (Math.abs(x[i] - x[v]) < 3 || Math.abs(y[i] - y[v]) < 3) {
                    f[i] = Math.min(f[v] + 1, f[i]);
                }
                if ((Math.abs(x[i] - x[v]) + Math.abs(y[i] - y[v]) <= 1)) {
                    f[i] = Math.min(f[i], f[v]);
                }
            }
        }
        if (ans == INF) {
            out.println(-1);
        } else {
            out.println(ans);
        }
    }

    public Solver(OkabeAndCity.FastReader in, OkabeAndCity.FastWriter out) {
        this.in = in;
        this.out = out;
        main();
        this.out.close();
    }
}


import java.util.*;
import java.io.*;
import java.math.BigInteger;

public class Main {
	public static void main(String args[]) {new Main().run();}

	FastReader in = new FastReader();
	PrintWriter out = new PrintWriter(System.out);
	void run(){
		work();
		out.flush();
	}
	long mod=1000000007;
	long gcd(long a,long b) {
		return a==0?b:gcd(b%a,a);
	}
	int[][] dir;
	int n,m,k;
	boolean[] vis1,vis2;
	HashSet<Long> set,vis;
	void work() {
		n=ni();m=ni();k=ni();
		ArrayList<Integer>[] row=(ArrayList<Integer>[])new ArrayList[n];
		ArrayList<Integer>[] col=(ArrayList<Integer>[])new ArrayList[m];
		for(int i=0;i<n;i++)row[i]=new ArrayList<>();
		for(int i=0;i<m;i++)col[i]=new ArrayList<>();
		vis1=new boolean[n];
		vis2=new boolean[m];
		set=new HashSet<>();
		vis=new HashSet<>();
		for(int i=0;i<k;i++) {
			int x=ni()-1,y=ni()-1;
			set.add(((long)x<<32)|y);
			row[x].add(y);
			col[y].add(x);
		}
		LinkedList<Long> q1=new LinkedList<>();
		LinkedList<Long> q2=new LinkedList<>();
		q1.add(0L);
		vis.add(0L);
		dir=new int[][] {{0,1},{1,0},{-1,0},{0,-1}};
		int cnt=0;
		while(q1.size()>0) {
			while(q1.size()>0) {
				long q=q1.poll();
				q2.add(q);
				int x=(int)(q>>32);
				int y=(int)(q&((1L<<32)-1));
				if(x==n-1&&y==m-1) {
					out.println(cnt);
					return;
				}
				add(x,y,q1);
				for(int i=0;i<4;i++) {
					int nx=x+dir[i][0],ny=y+dir[i][1];
					if(nx<0||nx>=n||ny<0||ny>=m||vis.contains(((long)nx<<32)|ny)||!set.contains(((long)nx<<32)|ny)) continue;
					q1.add(((long)nx<<32)|ny);
					vis.add(((long)nx<<32)|ny);
				}
			}
			cnt++;
			while(q2.size()>0) {
				long q=q2.poll();
				int x=(int)(q>>32);
				int y=(int)(q&((1L<<32)-1));
				if(x==n-2||x==n-1||y==m-2||y==m-1) {
					out.println(cnt);
					return;
				}
				for(int i=-2;i<=2;i++) {
					if(x+i>=0&&x+i<n&&!vis1[x+i]) {
						vis1[x+i]=true;
						for(int ny:row[x+i]) {
							if(!vis.contains(((long)(x+i)<<32)|ny)) {
								q1.add(((long)(x+i)<<32)|ny);
								vis.add(((long)(x+i)<<32)|ny);
							}
						}
					}
					if(y+i>=0&&y+i<m&&!vis2[y+i]) {
						vis2[y+i]=true;
						for(int nx:col[y+i]) {
							if(!vis.contains(((long)nx<<32)|(y+i))) {
								q1.add(((long)nx<<32)|(y+i));
								vis.add(((long)nx<<32)|(y+i));
							}
						}
					}
				}
			}
		}
		out.println(-1);
	}

	private void add(int x, int y, LinkedList<Long> q1) {
		for(int i=0;i<4;i++) {
			int nx=x+dir[i][0],ny=y+dir[i][1];
			if(nx<0||nx>=n||ny<0||ny>=m||vis.contains(((long)nx<<32)|ny)||!set.contains(((long)nx<<32)|ny)) continue;
			q1.add(((long)nx<<32)|ny);
			vis.add(((long)nx<<32)|ny);
		}
	}

	//input
	private ArrayList<Integer>[] ng(int n, int m) {
		ArrayList<Integer>[] graph=(ArrayList<Integer>[])new ArrayList[n];
		for(int i=0;i<n;i++) {
			graph[i]=new ArrayList<>();
		}
		for(int i=1;i<=m;i++) {
			int s=in.nextInt()-1,e=in.nextInt()-1;
			graph[s].add(e);
			graph[e].add(s);
		}
		return graph;
	}

	private ArrayList<long[]>[] ngw(int n, int m) {
		ArrayList<long[]>[] graph=(ArrayList<long[]>[])new ArrayList[n];
		for(int i=0;i<n;i++) {
			graph[i]=new ArrayList<>();
		}
		for(int i=1;i<=m;i++) {
			long s=in.nextLong()-1,e=in.nextLong()-1,w=in.nextLong();
			graph[(int)s].add(new long[] {e,w});
			graph[(int)e].add(new long[] {s,w});
		}
		return graph;
	}

	private int ni() {
		return in.nextInt();
	}

	private long nl() {
		return in.nextLong();
	}

	private long[] na(int n) {
		long[] A=new long[n];
		for(int i=0;i<n;i++) {
			A[i]=in.nextLong();
		}
		return A;
	}
	private int[] nia(int n) {
		int[] A=new int[n];
		for(int i=0;i<n;i++) {
			A[i]=in.nextInt();
		}
		return A;
	}
}

class FastReader
{
	BufferedReader br;
	StringTokenizer st;

	public FastReader()
	{
		br=new BufferedReader(new InputStreamReader(System.in));
	}

	public String next()
	{
		while(st==null || !st.hasMoreElements())//回车，空行情况
		{
			try {
				st = new StringTokenizer(br.readLine());
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return st.nextToken();
	}

	public int nextInt()
	{
		return Integer.parseInt(next());
	}

	public long nextLong()
	{
		return Long.parseLong(next());
	}
}


import java.io.*;
import java.math.*;
import java.util.*;
import java.awt.geom.*;

public class Main {
    static class FastReader {
        BufferedReader br;
        StringTokenizer tk;

        FastReader(InputStreamReader ir) {
            br = new BufferedReader(ir);
        }

        String next() {
            while ((tk == null) || (!tk.hasMoreElements())) {
                tk = new StringTokenizer(nextLine());
            }
            return tk.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        long nextLong() {
            return Long.parseLong(next());
        }

        String nextLine() {
            try {
                return br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
        }

    }

    static class FastWriter {
        BufferedWriter out;
        Formatter frm;

        FastWriter(OutputStreamWriter writer) {
            out = new BufferedWriter(writer);
            frm = new Formatter(out);
        }

        FastWriter printf(String format, Object... args) {
            frm.format(format, args).flush();
            return this;
        }

        FastWriter print(String str) {
            try {
                out.write(str);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return this;
        }

        FastWriter print(int x) {
            return print(Integer.toString(x));
        }

        FastWriter print(long x) {
            return print(Long.toString(x));
        }

        FastWriter print(double x) {
            return print(Double.toString(x));
        }

        FastWriter print(float x) {
            return print(Float.toString(x));
        }

        FastWriter print(short x) {
            return print(Short.toString(x));
        }

        FastWriter print(char c) {
            try {
                out.write(c);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return this;
        }

        FastWriter print(Object x) {
            return print(x.toString());
        }

        FastWriter println() {
            try {
                out.newLine();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return this;
        }

        FastWriter println(String str) {
            return print(str).println();
        }

        FastWriter println(long x) {
            return print(x).println();
        }

        FastWriter println(int x) {
            return print(x).println();
        }

        FastWriter println(double x) {
            return print(x).println();
        }

        FastWriter println(char x) {
            return print(x).println();
        }

        FastWriter println(float x) {
            return print(x).println();
        }

        FastWriter println(short x) {
            return print(x).println();
        }

        FastWriter println(Object x) {
            return print(x).println();
        }

        public void close() {
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    public static void main(String[] args) {
        new Solver(new FastReader(new InputStreamReader(System.in)), new FastWriter(new OutputStreamWriter(System.out)));
    }
}

class Solver {
    Main.FastReader in;
    Main.FastWriter out;

    void main() {
        int n = in.nextInt(), m = in.nextInt(), kk = in.nextInt();
        int[] x = new int[kk + 1], y = new int[kk + 1];
        int INF = kk * 11;
        boolean last = false;
        x[0] = y[0] = 1;
        int k = 1;
        for (int i = 0; i < kk; i++) {
            x[k] = in.nextInt();
            y[k] = in.nextInt();
            if ((x[i] != 1) || (y[i] != 1)) k++;
        }
        int[] f = new int[k + 2];
        f[k] = INF;
        Arrays.fill(f, INF);
        boolean[] w = new boolean[k + 1];
        Arrays.fill(w, false);
        int ans = INF;
        f[0] = 0;
        for (;;) {
            int v = k;
            for (int i = 0; i < k; i++) {
                if (!w[i] && f[i] < f[v]) v = i;
            }
            if (v == k) break;
            w[v] = true;
            if ((x[v] == n) && (y[v] == m)) {
                ans = Math.min(ans, f[v]);
            }

            if ((x[v] >= n - 1) || (y[v] >= m - 1)) {
                ans = Math.min(ans, f[v] + 1);
            }

            for (int i = 0; i < k; i++) {
                if (Math.abs(x[i] - x[v]) < 3 || Math.abs(y[i] - y[v]) < 3) f[i] = Math.min(f[v] + 1, f[i]);
                if ((Math.abs(x[i] - x[v]) + Math.abs(y[i] - y[v]) <= 1)) {
                    f[i] = Math.min(f[i], f[v]);
                }
            }
        }
        if (ans == INF) {
            out.println(-1);
        } else {
            out.println(ans);
        }
    }

    public Solver(Main.FastReader in, Main.FastWriter out) {
        this.in = in;
        this.out = out;
        main();
        this.out.close();
    }
}


#include<bits/stdc++.h>
using namespace std;
#define inf 0x7fffffff
#define ll long long
#define ull unsigned long long
const int mod = 1e4+7;
const ll INF = 1e18;
typedef pair<int, int>P;
const double eps = 1e-6;
const int maxn = 6e5+5;

struct edge
{
    int to, cost;
    edge(){}
    edge(int to, int cost):to(to), cost(cost){}
};
vector<edge>G[maxn];
int d[maxn];
P p[maxn];
map<P, int> mp;
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
void dijkstra(int s)
{
    priority_queue<P, vector<P>, greater<P> >q;
    fill(d, d+maxn, inf);
    d[s] = 0;
    q.push(P(0, s));
    while(!q.empty()) {
        P p = q.top();
        q.pop();
        int v = p.second;
        if(d[v] < p.first) continue;
        for(int i=0; i<G[v].size(); i++) {
            edge e = G[v][i];
            if(d[e.to] > d[v] + e.cost) {
                d[e.to] = d[v] + e.cost;
                q.push(P(d[e.to], e.to));
            }
        }
    }
}
int main()
{
    int n, m, k;
    cin >> n >> m >> k;
    int dd = 1e4+5;
    mp.clear();
    for(int i=1; i<=k; i++) {
        int r, c;
        scanf("%d%d", &r, &c);
        G[i].push_back(edge(r+dd, 1));
        G[i].push_back(edge(c+2*dd, 1));
        G[i].push_back(edge(r+1+dd, 1));
        G[i].push_back(edge(r-1+dd, 1));
        G[i].push_back(edge(c+1+2*dd, 1));
        G[i].push_back(edge(c-1+2*dd, 1));
        G[r+dd].push_back(edge(i, 0));
        G[c+2*dd].push_back(edge(i, 0));
        G[r+1+dd].push_back(edge(i, 0));
        G[r-1+dd].push_back(edge(i, 0));
        G[c+1+2*dd].push_back(edge(i, 0));
        G[c-1+2*dd].push_back(edge(i, 0));
        p[i] = P(r, c);
        mp[P(r, c)] = i;
    }
    for(int i=1; i<=k; i++) {
        for(int j=0; j<4; j++) {
            int x = p[i].first + dx[j];
            int y = p[i].second + dy[j];
            if(mp.find(P(x, y))!=mp.end()) {

                G[i].push_back(edge(mp[P(x, y)], 0));
            }
        }
    }
    if(mp.find(P(n, m))==mp.end()) {
        G[n+dd].push_back(edge(k+1, 0));
        G[m+2*dd].push_back(edge(k+1, 0));
    }
    dijkstra(mp[P(1, 1)]);
    int ans;
    if(mp.find(P(n, m))==mp.end()) {
        ans = d[k+1];
    }
    else {
        ans = d[mp[P(n, m)]];
    }
    if(ans == inf)
        ans = -1;
    cout << ans << endl;

}


#include <cstring>
#include <algorithm>
#include <cstdio>
#include <queue>

using namespace std;
const int INF = 0x3f3f3f3f;
const int MAXN = 10010;
const int MAXV = 100010;
const int MAXE = 1000010;

int n, m, k, r[MAXN], c[MAXN];
int s = -1, t = -1, tk = 0;

void input() {
	scanf( "%d%d%d", &n, &m, &k );
	for( int i = 0; i < k; ++i ) {
		scanf( "%d%d", r+i, c+i );
		if( r[i] == 1 && c[i] == 1 ) s = i;
		else if( r[i] == n && c[i] == m ) t = i;
	}
	if( t == -1 ) {
		r[k] = n, c[k] = m, ++k;
		t = k-1, tk = 1;
	}
}

namespace Graph {
	int head[MAXV], nxt[MAXE], to[MAXE], w[MAXE], eidx = 0;
	void init() {
		memset( head, -1, sizeof(head) );
	}
	void adde( int u, int v, int wei ) {
		to[eidx] = v, w[eidx] = wei, nxt[eidx] = head[u], head[u] = eidx++;
	}
}

int dis[MAXV], inq[MAXV];
queue<int> q;
int spfa() {
	using namespace Graph;
	memset( dis, 0x3f, sizeof(dis) );
	memset( inq, 0, sizeof(inq) );
	dis[s] = 0, inq[s] = 1, q.push(s);
	while( !q.empty() ) {
		int u = q.front(); q.pop();
		inq[u] = 0;
		for( int i = head[u]; ~i; i = nxt[i] ) {
			int v = to[i];
			if( dis[u] + w[i] < dis[v] ) {
				dis[v] = dis[u] + w[i];
				if( !inq[v] )
					inq[v] = 1, q.push(v);
			}
		}
	}
	return dis[t];
}

int id( int i, int j ) {
	if( i == 0 ) return k+j-1;
	else return k+n+j-1;
}

void solve() {
	Graph::init();
	for( int i = 0; i < k; ++i ) {
		int x = r[i], y = c[i];
		Graph::adde( i, id(0,x), 1 );
		Graph::adde( id(0,x), i, 0 );
		if( !(i == t && tk) ) {
			if( x > 1 ) {
				Graph::adde( i, id(0,x-1), 1 );
				Graph::adde( id(0,x-1), i, 0 );
			}
			if( x < n ) {
				Graph::adde( i, id(0,x+1), 1 );
				Graph::adde( id(0,x+1), i, 0 );
			}
		}
		Graph::adde( i, id(1,y), 1 );
		Graph::adde( id(1,y), i, 0 );
		if( !(i == t && tk) ) {
			if( y > 1 ) {
				Graph::adde( i, id(1,y-1), 1 );
				Graph::adde( id(1,y-1), i, 0 );
			}
			if( y < m ) {
				Graph::adde( i, id(1,y+1), 1 );
				Graph::adde( id(1,y+1), i, 0 );
			}
		}
	}
	for( int i = 0; i < k; ++i )
		for( int j = i+1; j < k; ++j ) {
			if( i == t && tk ) continue;
			if( j == t && tk ) continue;
			if( abs(r[i]-r[j]) == 1 && c[i] == c[j] ) {
				Graph::adde(i, j, 0);
				Graph::adde(j, i, 0);
			}
			if( abs(c[i]-c[j]) == 1 && r[i] == r[j] ) {
				Graph::adde(i, j, 0);
				Graph::adde(j, i, 0);
			}
		}
	int ans = spfa();
	printf( "%d\n", ans == INF ? -1 : ans );
}

int main() {
	input(), solve();
	return 0;
}


#include <cstring>
#include <algorithm>
#include <cstdio>
#include <queue>

using namespace std;
const int INF = 0x3f3f3f3f;
const int MAXN = 10010;
const int MAXV = 100010;
const int MAXE = 1000010;

int n, m, k, r[MAXN], c[MAXN];
int s = -1, t = -1, tk = 0;

void input() {
	scanf( "%d%d%d", &n, &m, &k );
	for( int i = 0; i < k; ++i ) {
		scanf( "%d%d", r+i, c+i );
		if( r[i] == 1 && c[i] == 1 ) s = i;
		else if( r[i] == n && c[i] == m ) t = i;
	}
	if( t == -1 ) {
		r[k] = n, c[k] = m, ++k;
		t = k-1, tk = 1;
	}
}

namespace Graph {
	int head[MAXV], nxt[MAXE], to[MAXE], w[MAXE], eidx = 0;
	void init() {
		memset( head, -1, sizeof(head) );
	}
	void adde( int u, int v, int wei ) {
		to[eidx] = v, w[eidx] = wei, nxt[eidx] = head[u], head[u] = eidx++;
	}
}

int dis[MAXV], inq[MAXV];
queue<int> q;
int spfa() {
	using namespace Graph;
	memset( dis, 0x3f, sizeof(dis) );
	memset( inq, 0, sizeof(inq) );
	dis[s] = 0, inq[s] = 1, q.push(s);
	while( !q.empty() ) {
		int u = q.front(); q.pop();
		inq[u] = 0;
		for( int i = head[u]; ~i; i = nxt[i] ) {
			int v = to[i];
			if( dis[u] + w[i] < dis[v] ) {
				dis[v] = dis[u] + w[i];
				if( !inq[v] )
					inq[v] = 1, q.push(v);
			}
		}
	}
	return dis[t];
}

int id( int i, int j ) {
	if( i == 0 ) return k+j-1;
	else return k+n+j-1;
}

void solve() {
	Graph::init();
	for( int i = 0; i < k; ++i ) {
		int x = r[i], y = c[i];
		Graph::adde( i, id(0,x), 1 );
		Graph::adde( id(0,x), i, 0 );
		if( !(i == t && tk) ) {
			if( x > 1 ) {
				Graph::adde( i, id(0,x-1), 1 );
				Graph::adde( id(0,x-1), i, 0 );
			}
			if( x < n ) {
				Graph::adde( i, id(0,x+1), 1 );
				Graph::adde( id(0,x+1), i, 0 );
			}
		}
		Graph::adde( i, id(1,y), 1 );
		Graph::adde( id(1,y), i, 1 );
		if( !(i == t && tk) ) {
			if( y > 1 ) {
				Graph::adde( i, id(1,y-1), 1 );
				Graph::adde( id(1,y-1), i, 0 );
			}
			if( y < m ) {
				Graph::adde( i, id(1,y+1), 1 );
				Graph::adde( id(1,y+1), i, 0 );
			}
		}
	}
	for( int i = 0; i < k; ++i )
		for( int j = i+1; j < k; ++j ) {
			if( i == t && tk ) continue;
			if( j == t && tk ) continue;
			if( abs(r[i]-r[j]) == 1 && c[i] == c[j] ) {
				Graph::adde(i, j, 0);
				Graph::adde(j, i, 0);
			}
			if( abs(c[i]-c[j]) == 1 && r[i] == r[j] ) {
				Graph::adde(i, j, 0);
				Graph::adde(j, i, 0);
			}
		}
	int ans = spfa();
	printf( "%d\n", ans == INF ? -1 : ans );
}

int main() {
	input(), solve();
	return 0;
}


#include <iostream>
#include <algorithm>
#include <string>
#include <set>
#include <map>
#include <cmath>
#include <fstream>
#include <iomanip>
#include <vector>
#include <string.h>
using namespace std;

typedef pair<int,int> pii;

const int MAX_N = 10000+10;
const int inf = 1000000000;

int n,m,k;
vector <pii> l;

vector <int> G[MAX_N], H[MAX_N];

int dis[MAX_N];
set <pii> s;

void dij(int q){
	for(int i=0;i<l.size();i++){
		dis[i]=inf;
	}
	dis[q]=0;
	for(int i=0;i<l.size();i++){
		s.insert(pii(dis[i],i));
	}
	while(s.size()){
		pii temp = *s.begin();
		s.erase(s.begin());
		int u = temp.second;
		for(int i=0;i<G[u].size();i++){
			int v = G[u][i];
			if(dis[v] > dis[u]){
				s.erase(pii(dis[v],v));
				dis[v]=dis[u];
				s.insert(pii(dis[v],v));
			}
		}
		for(int i=0;i<H[u].size();i++){
			int v = H[u][i];
			if(dis[v] > dis[u]+1){
				s.erase(pii(dis[v],v));
				dis[v]=dis[u]+1;
				s.insert(pii(dis[v],v));
			}
		}
	}
	if(dis[l.size()-1]==inf){
		dis[l.size()-1]=-1;
	}
}

int main(){
	scanf("%d%d%d",&n,&m,&k);
	for(int i=0;i<k;i++){
		int x,y;
		scanf("%d%d",&x,&y);
		l.push_back(pii(x,y));
	}
	sort(l.begin(),l.end());

	for(int i=0;i<l.size();i++){
		for(int j=0;j<l.size();j++)if(i!=j){
			if(abs(l[i].first-l[j].first)+abs(l[i].second-l[j].second) == 1){
				G[i].push_back(j);
			}else{
				if(abs(l[i].first-l[j].first)<=2){
					H[i].push_back(j);
				}else{
					if(abs(l[i].second-l[j].second)<=2){
						H[i].push_back(j);
					}
				}
			}
		}
	}
	if(!(l[k-1].first == n && l[k-1].second == m)){
		l.push_back(pii(n,m));
		for(int j=0;j<l.size()-1;j++){
			if(abs(l[k].first-l[j].first)<=1){
				H[k].push_back(j);
				H[j].push_back(k);
			}else{
				if(abs(l[k].second-l[j].second)<=1){
					H[k].push_back(j);
					H[j].push_back(k);
				}
			}
		}
	}
	dij(0);
	printf("%d\n",dis[l.size()-1]);
}


#include <bits/stdc++.h>

using namespace std;

#define INF (1 << 30)
#define MAX 10010

set<int> lit[MAX], visited[MAX], row[MAX], col[MAX], last_row, last_col;
int n, m, k, r[MAX], c[MAX], top_left, bottom_right;

void dfs(int x, int y, int comp){
    if(x < 1 or x > n or y < 1 or y > m or !lit[x].count(y) or visited[x].count(y)){
        return;
    }

    visited[x].insert(y);

    row[x].insert(comp);
    col[y].insert(comp);
    if(x == n and y == m) bottom_right = comp;
    if(x == 1 and y == 1) top_left = comp;

    dfs(x+1, y, comp);
    dfs(x-1, y, comp);
    dfs(x, y+1, comp);
    dfs(x, y-1, comp);
}

vector<int> adj[MAX];
int cost[MAX];

int main(){
    while(scanf("%d%d%d", &n, &m, &k) > 0){
        for(int i=1; i<=n or i<=m; i++){
            lit[i].clear();
            visited[i].clear();
            row[i].clear();
            col[i].clear();
        }

        for(int i=0; i<k; i++){
            scanf("%d%d", &r[i], &c[i]);
            lit[r[i]].insert(c[i]);
        }

        last_row.clear();
        last_col.clear();
        bottom_right = 0;

        int C = 0;
        for(int i=0; i<k; i++){
            if(!visited[r[i]].count(c[i])){
                dfs(r[i], c[i], ++C);
                adj[C].clear();
                cost[C] = -1;
            }
        }

        for(int i=1; i<=n; i++){
            for(set<int>::iterator i1=row[i].begin(); i1!=row[i].end(); i1++){
                set<int>::iterator i2 = i1; i2++;

                while(i2 != row[i].end()){
                    adj[*i1].push_back(*i2);
                    adj[*i2].push_back(*i1);
                    i2++;
                }

                if(i == n) break;
                i2 = row[i+1].begin();

                while(i2 != row[i+1].end()){
                    adj[*i1].push_back(*i2);
                    adj[*i2].push_back(*i1);
                    i2++;
                }

                if(i+1 == n) break;
                i2 = row[i+2].begin();

                while(i2 != row[i+2].end()){
                    adj[*i1].push_back(*i2);
                    adj[*i2].push_back(*i1);
                    i2++;
                }
            }
        }

        for(int i=1; i<=m; i++){
            for(set<int>::iterator i1=col[i].begin(); i1!=col[i].end(); i1++){
                set<int>::iterator i2 = i1; i2++;

                while(i2 != col[i].end()){
                    adj[*i1].push_back(*i2);
                    adj[*i2].push_back(*i1);
                    i2++;
                }

                if(i == m) break;
                i2 = col[i+1].begin();

                while(i2 != col[i+1].end()){
                    adj[*i1].push_back(*i2);
                    adj[*i2].push_back(*i1);
                    i2++;
                }

                if(i+1 == m) break;
                i2 = col[i+2].begin();

                while(i2 != col[i+2].end()){
                    adj[*i1].push_back(*i2);
                    adj[*i2].push_back(*i1);
                    i2++;
                }
            }
        }

        queue<int> q;

        cost[top_left] = 0;
        q.push(top_left);

        while(!q.empty()){
            int u = q.front(); q.pop();

            for(int i=0; i<adj[u].size(); i++){
                int v = adj[u][i];

                if(cost[v] == -1){
                    cost[v] = cost[u]+1;
                    q.push(v);
                }
            }
        }

        int ans = INF;

        for(int i=n-1; i<=n; i++){
            for(set<int>::iterator it=row[i].begin(); it!=row[i].end(); it++){
                if(cost[*it] != -1) ans = min(ans, cost[*it]+1);
            }
        }

        for(int i=m-1; i<=m; i++){
            for(set<int>::iterator it=col[i].begin(); it!=col[i].end(); it++){
                if(cost[*it] != -1) ans = min(ans, cost[*it]+1);
            }
        }

        if(bottom_right) ans = min(ans, cost[bottom_right]);

        printf("%d\n", ans == INF ? -1 : ans);
    }
}


#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
#include<deque>
#define pb push_back
#define pf push_front

using namespace std;
struct lit
{
	int x, y;
};
struct qnode
{
	int ind, lite, dist;
};
deque< qnode > q;
vector<int> row[10005], col[10005];
lit arr[10005];
int n, m, k, strt, depth[10005][7], inf=1e9;
bool visited[10005][7], actvis[10005][7];
void pusher(qnode child)
{
	if(!visited[child.ind][child.lite] && (child.ind!=k || child.lite==2 || child.lite==5))
	{
		q.pb(child);
		visited[child.ind][child.lite]=1;
	}
}
void bfs(int node, int light)
{
	//cout << node << " " << light << " - " << depth[node][light] <<endl;
	actvis[node][light]=true;
	int x = arr[node].x; int y = arr[node].y;
	int d=depth[node][light];
	qnode child;
	child.dist=d+1;
	if(x!=1)
	{
		for(int i = 0; i < row[x-2].size(); i++)
		{
			child.ind=row[x-2][i];
			child.lite=3;	pusher(child);
		}
	}
	for(int i = 0; i < row[x-1].size(); i++)
	{
		child.ind=row[x-1][i];
		child.lite=2;	pusher(child);
		child.lite=3;	pusher(child);
	}
	for(int i = 0; i < row[x].size(); i++)
	{
		child.ind=row[x][i];
		child.lite=1;	pusher(child);
		child.lite=2;	pusher(child);
		child.lite=3;	pusher(child);
	}
	for(int i = 0; i < row[x+1].size(); i++)
	{
		child.ind=row[x+1][i];
		child.lite=2;	pusher(child);
		child.lite=1;	pusher(child);
	}
	for(int i = 0; i < row[x+2].size(); i++)
	{
		child.ind=row[x+2][i];
		child.lite=1;	pusher(child);
	}
	if(y!=1)
	{
		for(int i = 0; i < col[y-2].size(); i++)
		{
			child.ind=col[y-2][i];
			child.lite=6;	pusher(child);
		}
	}
	for(int i = 0; i < col[y-1].size(); i++)
	{
		child.ind=col[y-1][i];
		child.lite=5;	pusher(child);
		child.lite=6;	pusher(child);
	}
	for(int i = 0; i < col[y].size(); i++)
	{
		child.ind=col[y][i];
		child.lite=4;	pusher(child);
		child.lite=5;	pusher(child);
		child.lite=6;	pusher(child);
	}
	for(int i = 0; i < col[y+1].size(); i++)
	{
		child.ind=col[y+1][i];
		child.lite=4;	pusher(child);
		child.lite=5;	pusher(child);
	}
	for(int i = 0; i < col[y+2].size(); i++)
	{
		child.ind=col[y+2][i];
		child.lite=4;	pusher(child);
	}
	child.dist=d;
	for(int i = 0; i < col[y].size(); i++)
	{
		child.ind=col[y][i];
		if(arr[child.ind].x==x-1)
		{
			if(light==1) child.lite=2;
			else if(light==2) child.lite=3;
			else if(light==3) child.lite=0;
			else child.lite=light;
			if(!actvis[child.ind][child.lite])
			{
				q.pf(child);
			}
		}
		else if(arr[child.ind].x==x+1)
		{
			if(light==1) child.lite=0;
			else if(light==2) child.lite=1;
			else if(light==3) child.lite=2;
			else child.lite=light;
			if(!actvis[child.ind][child.lite])
			{
				q.pf(child);
			}
		}
	}
	for(int i = 0; i < row[x].size(); i++)
	{
		child.ind=row[x][i];
		if(arr[child.ind].y==y-1)
		{
			if(light==4) child.lite=5;
			else if(light==5) child.lite=6;
			else if(light==6) child.lite=0;
			else child.lite=light;
			if(!actvis[child.ind][child.lite])
			{
				q.pf(child);
			}
		}
		else if(arr[child.ind].y==y+1)
		{
			if(light==4) child.lite=0;
			else if(light==5) child.lite=4;
			else if(light==6) child.lite=5;
			else child.lite=light;
			if(!actvis[child.ind][child.lite])
			{
				q.pf(child);
			}
		}
	}
	while(q.size()>0)
	{
		child=q.front();
		q.pop_front();
		if(!actvis[child.ind][child.lite])
		{
			depth[child.ind][child.lite]=child.dist;
			bfs(child.ind, child.lite);
		}
	}
}
int main()
{
	cin >> n >> m >> k;
	bool endlit=false;
	for(int i = 0; i < k; i++)
	{
		cin >> arr[i].x >> arr[i].y;
		if(arr[i].x==1 && arr[i].y==1) strt=i;
		else if(arr[i].x==n && arr[i].y==m) endlit=true;
		row[arr[i].x].pb(i);
		col[arr[i].y].pb(i);
	}
	for(int i = 0; i <= k; i++)
	{
		for(int j = 0; j < 7; j++)
		{
			depth[i][j]=-1;
		}
	}
	arr[k].x=n; arr[k].y=m;
	row[n].pb(k);
	col[m].pb(k);
	depth[strt][0]=0;
	visited[strt][0]=1;
	bfs(strt, 0);
	int mn=inf;
	if(endlit)
	{
		for(int i = 0; i < 7; i++)
		{
	//		cout << i << " = " << depth[k][i] << endl;
			if(depth[k][i]<mn && depth[k][i]!=-1)
			{
				mn=depth[k][i];
			}
		}
	}
	if(mn!=inf)
	{
		cout << mn << endl;
		return 0;
	}
	if(depth[k][2]==-1)
	{
		cout << depth[k][5];
	}
	else if(depth[k][5]==-1)
	{
		cout << depth[k][2];
	}
	else cout << min(depth[k][2], depth[k][5]);
}