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

// 감시
@SuppressWarnings("unchecked")
class Main {

    static int n, m, size = Integer.MAX_VALUE, cctvCount;
    static int[][] area, copyMap, dir = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
    static boolean[][] visit;
    static ArrayList<CCTV> cctvList = new ArrayList<>();
    static class CCTV {
        int x;
        int y;
        int num;
        CCTV(int x, int y, int num) {
            this.x = x;
            this.y = y;
            this.num = num;
        }
    }
    

    public static void main(String[] args) throws IOException {
        input();
        process();
    }

    static void input() throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        n = Integer.parseInt(st.nextToken());
        m = Integer.parseInt(st.nextToken());

        area = new int[n + 1][m + 1];
        visit = new boolean[n + 1][m + 1];

        for (int i = 1; i <= n; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 1; j <= m; j++) {
                area[i][j] = Integer.parseInt(st.nextToken());
                if (area[i][j] > 0 && area[i][j] < 6) {
                    cctvList.add(new CCTV(i, j, area[i][j]));
                }
            }
        }

        cctvCount = cctvList.size();
    }

    static void process() {
        func(0, 0, area);
        System.out.println(size);
    }

    static void func(int depth, int start, int[][] map) {
        if (cctvCount == 0) {
            copy(area);
            size = checkArea();
            return;
        }
        if (cctvCount == depth) {
            int width = checkArea();
            size = Math.min(size, width);
            return;
        }

        for (int i = 0; i < 4; i++) {
            copy(map);
            CCTV cctv = cctvList.get(start);
            if (cctv.num == 2 || cctv.num == 5) {
                if (i == 2)
                    break;
                if (cctv.num == 5 && i == 1)
                    break;
            }
            changeView(cctv, i);
            func(depth + 1, start + 1, copyMap);
        }
    }

    static void copy(int[][] map) {
        copyMap = new int[n + 1][m + 1];
        for (int i = 0; i <= n; i++) {
            for (int j = 0; j <= m; j++) {
                copyMap[i][j] = map[i][j];
            }
        }
    }

    static void changeView(CCTV cctv, int direction) {
        switch(cctv.num) {
            case 1:
                bfs(direction, cctv);
                break;
            case 2:
                bfs(direction, cctv);
                bfs((direction + 2) % 4, cctv);
                break;
            case 3:
                bfs(direction, cctv);
                bfs((direction + 1) % 4, cctv);
                break;
            case 4:
                bfs(direction, cctv);
                bfs((direction + 1) % 4, cctv);
                bfs((direction + 2) % 4, cctv);
                break;
            case 5:
                bfs(direction, cctv);
                bfs((direction+1) % 4, cctv);
                bfs((direction+2) % 4, cctv);
                bfs((direction+3) % 4, cctv);
                break;
        }
    }

    static void bfs(int direction, CCTV cctv) {
        int x = cctv.x;
        int y = cctv.y;
        while(true) {
            x += dir[direction][0];
            y += dir[direction][1];

            if (x < 1 || y < 1 || x > n || y > m) break;
            if (copyMap[x][y] == 6) break;
            if (copyMap[x][y] > 1 && copyMap[x][y] < 6) continue;
            
            copyMap[x][y] = 7;
        }
    }

    static int checkArea() {
        int width = 0;
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                if (copyMap[i][j] == 0) {
                    width++;
                }
            }
        }
        return width;
    }
}