方格取数 3
时间限制: 2 s
空间限制: 256000 KB
题目等级 : 大师 Master
题目描述 Description
问题描述:
在一个有m*n 个方格的棋盘中,每个方格中有一个正整数。现要从方格中取数,使任
意2 个数所在方格没有公共边,且取出的数的总和最大。试设计一个满足要求的取数算法。
编程任务:
对于给定的方格棋盘,按照取数要求编程找出总和最大的数。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
const int NN=1000;
const int inf=0x3f3f3f3f;
int N,M,ans,head[NN],next[NN<<3],to[NN<<3],c[NN<<3],tot=1,S=0,T=999;
int dist[NN],last[NN],num[NN],SUM;
bool Exit;
void add(int a,int b,int v)
{
to[++tot]=b;
c[tot]=v;
next[tot]=head[a];
head[a]=tot;
last[a]=head[a];
}
void input()
{
int x,t=0,color=0;
scanf("%d%d",&N,&M);
for (int i=1;i<=N;i++)
for (int j=1;j<=M;j++)
{
if (j==1) {color=(M&1)?!color:color;}
else color=!color;
scanf("%d",&x);
SUM+=x;
t++;
if(color)
{
add(S,t,x),add(t,S,0);
if (i>1) add(t,t-M,inf),add(t-M,t,0);
if (i<N) add(t,t+M,inf),add(t+M,t,0);
if (j>1) add(t,t-1,inf),add(t-1,t,0);
if (j<M) add(t,t+1,inf),add(t+1,t,0);
}
else add(t,T,x),add(T,x,0);
}
}
int dfs(int x,int in)
{
if (x==T) return in;
int t,ans=0;
for (int p=last[x];p;last[x]=p=next[p])
if(c[p]&&dist[x]==dist[to[p]]+1)
{
ans+= t=dfs(to[p],min(c[p],in-ans));
c[p]-=t;c[p^1]+=t;
if(Exit||ans==in) return ans;
}
Exit=--num[dist[x]]==0;num[++dist[x]]++;
last[x]=head[x];
return ans;
}
int main()
{
int flow=0;
input();
num[0]=N*M+2;
while(!Exit) flow+=dfs(S,inf);
printf("%d\n",SUM-flow);
return 0;
}