/*最大点权独立集=sum-最小点权覆盖*/ #include<stdio.h> #include<string.h> #include<queue> using namespace std; #define inf 0x3fffffff #define ll __int64 #define N 3000 struct node { ll u,v,w,next; }bian[N*N*2]; ll ma[N][N],id[N][N],head[N],yong,s,t,dis[N];; void addedge(ll u,ll v,ll w) { bian[yong].u=u; bian[yong].v=v; bian[yong].w=w; bian[yong].next=head[u]; head[u]=yong++; } void add(ll u,ll v,ll w) { addedge(u,v,w); addedge(v,u,0); } void init() { yong=0; memset(head,-1,sizeof(head)); memset(dis,-1,sizeof(dis)); } void bfs() { ll u,v,i; queue<ll>q; q.push(t); dis[t]=0; while(!q.empty()) { u=q.front(); q.pop(); for(i=head[u]; i!=-1; i=bian[i].next) { v=bian[i].v; if(dis[v]==-1) { dis[v]=dis[u]+1; q.push(v); } } } return ; } ll ISAP() { ll sum=0; bfs(); ll gap[N],cur[N],stac[N],top,i; memset(gap,0,sizeof(gap)); for(i=s; i<=t; i++) { gap[dis[i]]++; cur[i]=head[i]; } ll k=s; top=0; while(dis[s]<t+1) { if(k==t) { ll minn=inf,index; for(i=0; i<top; i++) { ll e=stac[i]; if(minn>bian[e].w) { minn=bian[e].w; index=i; } } for(i=0; i<top; i++) { ll e=stac[i]; bian[e].w-=minn; bian[e^1].w+=minn; } sum+=minn; top=index; k=bian[stac[top]].u; } for(i=cur[k]; i!=-1; i=bian[i].next) { ll v=bian[i].v; if(bian[i].w&&dis[k]==dis[v]+1) { cur[k]=i; k=v; stac[top++]=i; break; } } if(i==-1) { ll m=t+1; for(i=head[k]; i!=-1; i=bian[i].next) if(m>dis[bian[i].v]&&bian[i].w) { m=dis[bian[i].v]; cur[k]=i; } if(--gap[dis[k]]==0)break; gap[dis[k]=m+1]++; if(k!=s) k=bian[stac[--top]].u; } } return sum; } int main() { ll n,m,i,j,cnt; ll sum; while(scanf("%I64d%I64d",&n,&m)!=EOF) { init(); cnt=1; sum=0;s=0;t=n*m+1; for(i=1; i<=n; i++) for(j=1; j<=m; j++) { scanf("%I64d",&ma[i][j]); id[i][j]=cnt++; sum+=ma[i][j]; } for(i=1; i<=n; i++) for(j=1; j<=m; j++) { if((i+j)&1) { add(s,id[i][j],ma[i][j]); if(i<=n-1) add(id[i][j],id[i+1][j],inf); if(j<=m-1) add(id[i][j],id[i][j+1],inf); if(i>=2) add(id[i][j],id[i-1][j],inf); if(j>=2) add(id[i][j],id[i][j-1],inf); } else add(id[i][j],t,ma[i][j]); } printf("%I64d ",sum-ISAP()); } return 0; }