#include<bits/stdc++.h>
using namespace std;
#define maxn 200005
#define LL long long
inline int read(){
char c=getchar();
int x=0,w=1;
while(c>'9'||c<'0'){
c=getchar();
}
while(c>='0'&&c<='9'){
x=x*10+c-'0';
c=getchar();
}
return x*w ;
}
int n,m;
bool vis[8*maxn];
LL S,T,f,maxflow,mincost,FLAG;
LL dis[8*maxn],pre[8*maxn],last[8*maxn],flow[8*maxn],color[8*maxn];
int dx[5]={0,-1,0,1,0},dy[5]={0,0,1,0,-1},opp[5]={0,3,4,1,2};
inline int id(int x,int y,int k){
return (x-1)*m+y+m*n*k;
}
struct Edge{
LL to,next,flow,dis;
}edge[maxn];
int head[maxn],num_edge;
deque <int> q;
inline void add(int from,int to,int flow,int dis){
edge[++num_edge].next=head[from];
edge[num_edge].to=to;
edge[num_edge].flow=flow;
edge[num_edge].dis=dis;
head[from]=num_edge;
}
inline void Add(int from,int to,int flow,int dis){
if(FLAG==1){
add(to,from,flow,dis);
add(from,to,0,-dis);
return;
}
add(from,to,flow,dis);
add(to,from,0,-dis);
}
inline void build(int flag,int x,int y){
if(flag==1){
Add(id(x,y,0),id(x,y,1),1,0);
Add(id(x,y,1),id(x,y,2),1,1);
Add(id(x,y,1),id(x,y,3),1,2);
Add(id(x,y,1),id(x,y,4),1,1);
}
else if(flag==2){
Add(id(x,y,0),id(x,y,2),1,0);
Add(id(x,y,2),id(x,y,1),1,1);
Add(id(x,y,2),id(x,y,3),1,1);
Add(id(x,y,2),id(x,y,4),1,2);
}
else if(flag==3){
Add(id(x,y,0),id(x,y,1),1,0);
Add(id(x,y,0),id(x,y,2),1,0);
Add(id(x,y,1),id(x,y,3),1,1);
Add(id(x,y,2),id(x,y,4),1,1);
}
else if(flag==4){
Add(id(x,y,0),id(x,y,3),1,0);
Add(id(x,y,3),id(x,y,1),1,2);
Add(id(x,y,3),id(x,y,2),1,1);
Add(id(x,y,3),id(x,y,4),1,1);
}
else if(flag==5){
Add(id(x,y,0),id(x,y,1),1,0);
Add(id(x,y,0),id(x,y,3),1,0);
}
else if(flag==6){
Add(id(x,y,0),id(x,y,2),1,0);
Add(id(x,y,0),id(x,y,3),1,0);
Add(id(x,y,3),id(x,y,1),1,1);
Add(id(x,y,2),id(x,y,4),1,1);
}
else if(flag==7){
Add(id(x,y,0),id(x,y,1),1,0);
Add(id(x,y,0),id(x,y,2),1,0);
Add(id(x,y,0),id(x,y,3),1,0);
Add(id(x,y,1),id(x,y,4),1,1);
Add(id(x,y,2),id(x,y,4),1,2);
Add(id(x,y,3),id(x,y,4),1,1);
}
else if(flag==8){
Add(id(x,y,0),id(x,y,4),1,0);
Add(id(x,y,4),id(x,y,1),1,1);
Add(id(x,y,4),id(x,y,2),1,2);
Add(id(x,y,4),id(x,y,3),1,1);
}
else if(flag==9){
Add(id(x,y,0),id(x,y,1),1,0);
Add(id(x,y,0),id(x,y,4),1,0);
Add(id(x,y,1),id(x,y,3),1,1);
Add(id(x,y,4),id(x,y,2),1,1);
}
else if(flag==10){
Add(id(x,y,0),id(x,y,2),1,0);
Add(id(x,y,0),id(x,y,4),1,0);
}
else if(flag==11){
Add(id(x,y,0),id(x,y,1),1,0);
Add(id(x,y,0),id(x,y,2),1,0);
Add(id(x,y,0),id(x,y,4),1,0);
Add(id(x,y,1),id(x,y,3),1,2);
Add(id(x,y,2),id(x,y,3),1,1);
Add(id(x,y,4),id(x,y,3),1,1);
}
else if(flag==12){
Add(id(x,y,0),id(x,y,3),1,0);
Add(id(x,y,0),id(x,y,4),1,0);
Add(id(x,y,3),id(x,y,1),1,1);
Add(id(x,y,4),id(x,y,2),1,1);
}
else if(flag==13){
Add(id(x,y,0),id(x,y,1),1,0);
Add(id(x,y,0),id(x,y,3),1,0);
Add(id(x,y,0),id(x,y,4),1,0);
Add(id(x,y,1),id(x,y,2),1,1);
Add(id(x,y,3),id(x,y,2),1,1);
Add(id(x,y,4),id(x,y,2),1,2);
}
else if(flag==14){
Add(id(x,y,0),id(x,y,2),1,0);
Add(id(x,y,0),id(x,y,3),1,0);
Add(id(x,y,0),id(x,y,4),1,0);
Add(id(x,y,2),id(x,y,1),1,1);
Add(id(x,y,3),id(x,y,1),1,2);
Add(id(x,y,4),id(x,y,1),1,1);
}
else if(flag==15){
Add(id(x,y,0),id(x,y,1),1,0);
Add(id(x,y,0),id(x,y,2),1,0);
Add(id(x,y,0),id(x,y,3),1,0);
Add(id(x,y,0),id(x,y,4),1,0);
}
if(FLAG==0){
for(int i=1;i<=4;i++){
if(x+dx[i]>=1&&y+dy[i]>=1&&x+dx[i]<=n&&y+dy[i]<=m){
Add(id(x,y,i),id(x+dx[i],y+dy[i],opp[i]),1,0);
}
}
}
}
inline bool spfa(int s,int t){
memset(dis,0x7f,sizeof(dis));
memset(flow,0x7f,sizeof(flow));
memset(vis,0,sizeof(vis));
q.push_front(s); vis[s]=1; dis[s]=0; pre[t]=-1;
while (!q.empty()){
int now=q.front();
q.pop_front();
vis[now]=0;
for (int i=head[now]; i!=-1; i=edge[i].next){
if (edge[i].flow>0 && dis[edge[i].to]>dis[now]+edge[i].dis){
dis[edge[i].to]=dis[now]+edge[i].dis;
pre[edge[i].to]=now;
last[edge[i].to]=i;
flow[edge[i].to]=min(flow[now],edge[i].flow);
if (!vis[edge[i].to]){
vis[edge[i].to]=1;
if(!q.empty()&&dis[edge[i].to]<dis[q.front()]){
q.push_front(edge[i].to);
}
else{
q.push_back(edge[i].to);
}
}
}
}
}
return pre[t]!=-1;
}
void MCMF(){
while (spfa(S,T)){
int now=T;
maxflow+=flow[T];mincost+=flow[T]*dis[T];
while (now!=S){
edge[last[now]].flow-=flow[T];
edge[last[now]^1].flow+=flow[T];
now=pre[now];
}
}
}
int main(){
memset(head,-1,sizeof(head)); num_edge=-1;
int x,s,sum=0;
n=read();
m=read();
S=0;
T=m*n*5+1;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
x=read();
if(x==0){
continue;
}
s=0;
if(x&1){s++;}
if(x&2){s++;}
if(x&4){s++;}
if(x&8){s++;}
FLAG=0;
if((i+j)&1){
Add(id(i,j,0),T,s,0);
FLAG=1;
build(x,i,j);
sum+=s;
}
else{
Add(S,id(i,j,0),s,0);
build(x,i,j);
sum+=s;
}
}
}
MCMF();
if(maxflow<(sum)/2){
cout<<"-1";
}
else{
cout<<mincost;
}
return 0;
}