#include<bits/stdc++.h>
using namespace std;
template<typename T>inline void read(T &x){
x=0;int f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
x*=f;
}
template<typename T,typename ...Args>
inline void read(T &x,Args &...rest){read(x);read(rest...);}
constexpr int N=10005;
struct edge{int to,nx,c,w;}e[50000];
int head[N],tot=1,should;
inline void add(int u,int v,int w,int ty){
if(ty)swap(u,v);
e[++tot]={v,head[u],1,w};
head[u]=tot;
e[++tot]={u,head[v],0,-w};
head[v]=tot;
}
#define repg(i,u,v) for(int i=head[u],v=e[i].to;i;i=e[i].nx,v=e[i].to)
int n,m,s,t;
int now[N],maxcurrent,mincost,dis[N];
bool vis[N];
inline bool spfa(){
memset(vis,0,sizeof(vis));
memset(dis,127,sizeof(dis));
memcpy(now,head,sizeof(head));
dis[t]=0;
deque<int> Q;
Q.push_front(t);
while(!Q.empty()){
int u=Q.front();
Q.pop_front();
vis[u]=0;
repg(i,u,v){
if(e[i^1].c>0&&dis[u]-e[i].w<dis[v]){
dis[v]=dis[u]-e[i].w;
if(!vis[v]){
vis[v]=1;
if(Q.empty()||dis[v]>dis[Q.front()])Q.push_back(v);
else Q.push_front(v);
}
}
}
}
return dis[s]!=2139062143;
}
inline int dfs(int u,int remain){
if(u==t)return vis[t]=1,remain;
int current=0,cap;
vis[u]=1;
for(int i=now[u];i&&remain>0;i=e[i].nx){
int v=e[i].to;
now[u]=i;
if(e[i].c==0||vis[v]||dis[u]-e[i].w!=dis[v])continue;
cap=dfs(v,min(remain,e[i].c));
e[i].c-=cap;
e[i^1].c+=cap;
current+=cap;
remain-=cap;
mincost+=cap*e[i].w;
}
return current;
}
inline void MCMC(){
while(spfa()){
vis[t]=1;
while(vis[t]){
memset(vis,0,sizeof(vis));
maxcurrent+=dfs(s,INT_MAX);
}
}
}
inline int up(int x,int y){return 4*( (x-1)*m+y ) ;}
inline int right(int x,int y){return 4*( (x-1)*m+y ) + 1;}
inline int down(int x,int y){return 4*( (x-1)*m+y ) + 2;}
inline int left(int x,int y){return 4*( (x-1)*m+y ) + 3;}
int main(){
read(n,m);
s=0;t=1;int ty=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
int st,a=up(i,j),b=right(i,j),c=down(i,j),d=left(i,j);
ty^=1;
read(st);
if(ty==0){
if(st&1)add(s,a,0,0);
if(st>>1&1)add(s,b,0,0);
if(st>>2&1)add(s,c,0,0);
if(st>>3&1)add(s,d,0,0);
if(i>1)add(a,down(i-1,j),0,0);
if(j<m)add(b,left(i,j+1),0,0);
if(i<n)add(c,up(i+1,j),0,0);
if(j>1)add(d,right(i,j-1),0,0);
}
else{
if(st&1)add(a,t,0,0);
if(st>>1&1)add(b,t,0,0);
if(st>>2&1)add(c,t,0,0);
if(st>>3&1)add(d,t,0,0);
}
should+=__builtin_popcount(st);
switch(st){
case 1:
add(a,b,1,ty);
add(a,d,1,ty);
add(a,c,2,ty);
break;
case 2:
add(b,a,1,ty);
add(b,c,1,ty);
add(b,d,2,ty);
break;
case 3:
add(a,c,1,ty);
add(b,d,1,ty);
break;
case 4:
add(c,b,1,ty);
add(c,d,1,ty);
add(c,a,2,ty);
break;
case 6:
add(b,d,1,ty);
add(c,a,1,ty);
break;
case 7:
add(c,d,1,ty);
add(a,d,1,ty);
add(b,d,2,ty);
break;
case 8:
add(d,a,1,ty);
add(d,c,1,ty);
add(d,b,2,ty);
break;
case 9:
add(a,c,1,ty);
add(d,b,1,ty);
break;
case 11:
add(b,c,1,ty);
add(d,c,1,ty);
add(a,c,2,ty);
break;
case 12:
add(d,b,1,ty);
add(c,a,1,ty);
break;
case 13:
add(a,b,1,ty);
add(c,b,1,ty);
add(d,b,2,ty);
break;
case 14:
add(d,a,1,ty);
add(b,a,1,ty);
add(c,a,2,ty);
break;
}
}
}
//for(int i=0;i<=left(n,m)+1;i++)for(int j=head[i];j;j=e[j].nx)cerr<<i<<' '<<e[j].to<<endl;
MCMC();
printf("%d",maxcurrent*2==should?mincost:-1);
return 0;
}
错的全都是应该有答案但是输出-1.