题解:方格取数问题

传送门

在一个有 m*n 个方格的棋盘中,每个方格中有一个正整数。现要从方格中取数,使任意 2 个数所在方格没有公共边,且取出的数的总和最大。试设计一个满足要求的取数算法。对于给定的方格棋盘,按照取数要求编程找出总和最大的数。

这个题目也是很明显的网络流,奇偶性建图,最后总和-最小割即为答案

#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;
const int N=10100,M=202000,INF=(1<<29);
int tt=1,n,m,s,t,head[N],dis[N],vis[N],dep[N];
long long maxf=0; 
struct pr {int next,to,w;}a[M];

inline int read ()
{
    int s=0;
    char ch=getchar ();
    while (ch>'9'||ch<'0') ch=getchar ();
    while (ch>='0'&&ch<='9') {s=s*10+ch-'0';ch=getchar ();}
    return s;
}

void add (int u,int v,int w)
{
    a[++tt].next=head[u];a[tt].to=v;a[tt].w=w;head[u]=tt;
    a[++tt].next=head[v];a[tt].to=u;a[tt].w=0;head[v]=tt;
}

int dinic (int x,int flow)
{
    if (x==t) return flow;
    int rest=flow,k,y;
    for (int i=head[x];i;i=a[i].next) {
        y=a[i].to;
        if (a[i].w&&dep[y]==dep[x]+1) {
            k=dinic (y,min (rest,a[i].w));
            if (!k) dep[y]=0;//剪枝 
            a[i].w-=k;
            a[i^1].w+=k;
            rest-=k;
        }
    }
    return flow-rest;
}

bool bfs ()
{
    int x,y;
    queue <int> q;
    for (int i=1;i<=n*m+2;i++) dep[i]=0;
    q.push(s);dep[s]=1;
    while (!q.empty()) {
        x=q.front();q.pop();
		for (int i=head[x];i;i=a[i].next) {
            y=a[i].to;
            if (a[i].w&&!dep[y]) {
                dep[y]=dep[x]+1;
                q.push(y);
//                if (y==t) return 1;
            }
        }
    }
    return dep[t];
}

int x[]={1,0,-1,0};
int y[]={0,1,0,-1};

int main ()
{
//	freopen("y.txt","r",stdin);
    
    n=read(),m=read();
    s=m*n+1,t=n*m+2;
    for(int i=1;i<=n;++i)
    	for(int j=1;j<=m;++j) {
    		int w=read();
    		maxf+=w;
			if((i+j)%2==0) add(s,(i-1)*m+j,w);
			else add((i-1)*m+j,t,w);
		}
    for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j) {
			if((i+j)%2==0) {
				for(int k=0;k<=3;++k) {
					int r=i+x[k],c=j+y[k];
					if(r<=n&&r>=1&&c<=m&&c>=1)
						add((i-1)*m+j,(r-1)*m+c,INF);
				}
			}
		}    
	int in;
    while (bfs ()) {while ((in=dinic (s,INF))) maxf-=in;} 
    cout<<maxf;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43464026/article/details/87451891