码迷,mamicode.com
首页 > 其他好文 > 详细

[TYVJ1338] QQ农场

时间:2017-09-23 17:14:49      阅读:174      评论:0      收藏:0      [点我收藏+]

标签:++   ring   获得   oid   out   str   main   必须   top   

描述

这个农场和游戏中略有不同。土地实际上是一个边长为N的正方形,由N*N块土地组成。
在每块土地上,都种有一种农作物。如果他选择摘取一块土地上的农作物,就能获得一个固定的利润(当然,这个利润是正数)。不同土地上的利润多半是不同的。
贪心的Sandytea本想摘取所有土地上的农作物。但是正当他准备行动时,却被告知不允许摘取了两块有公共边的土地上的作物,否则就会被主人的狗发现。
Sandytea想知道,在不被狗抓住的前提下,他能获得的最大利益是多少。

输入格式

第一行:一个整数N,表示土地是一个边长为N的正方形。
下面N行:每行N个正整数,描述了各块土地上的农作物的单位价值。

输出格式

输出一行,包含一个整数,为最大的收益。

测试样例1

输入


7 7 
54 54

输出

61

备注

数据范围:
有10分的数据满足:N≤6
另有20分的数据满足:N≤13
另有30分的数据满足:N≤50
另有40分的数据满足:N≤200
所有数据满足:每块土地上作物的价值不超过100。
 
最小割:最大化利益=最小化损失
把网格黑白染色,
技术分享
由源点向黑格连容量为格点权值的边,白格向汇点连容量为格点权值的边,每个黑格子向相邻的格子连容量为inf的边
把黑格子割到源点表示采摘该格作物,否则不采摘
把白格子割到汇点表示采摘该格作物,否则不采摘
为什么相邻格子要连INF的边呢?
题目说,不能采相邻格子的作物,而如果连INF的边,就说明这条边必不可能被割断,相邻格子就必不可能都能被采摘(否则S到T连通)
注意,必须从黑格(即为与源点连边的格子)向白格(即为与汇点连边的格子)连边
不能从白格向黑格连边或黑白格互相连边(即从黑格向白格连边,白格也向黑格连边)
为什么呢?
如果互相连边,那么下图1,3两个点就变相有了限制关系,而事实上并不是取了1号点就不能取3号点(1号点只与2号点相邻)
技术分享技术分享
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int INF=1999999999;
int h[1000000],next[1000000],cap[1000000],to[1000000],k=1;
int level[40100],que[40100],head,tail,iter[40100],n;
int x[4]={-1,0,1,0},y[4]={0,-1,0,1}; 
void ins(int u,int v,int c){next[++k]=h[u];h[u]=k;to[k]=v;cap[k]=c;}
int get(int i,int j){return (i-1)*n+j;}
bool bfs(int S,int T)
{
    memset(level,0,sizeof(level));
    head=tail=0;que[tail++]=S;level[S]=1;
    while(head<tail)
    {
        int u=que[head++];
        for(int i=h[u];i;i=next[i])
        {
            int v=to[i];
            if(!level[v]&&cap[i])
            {
                level[v]=level[u]+1;que[tail++]=v;
            }
        }
    }
    if(!level[T])return 0;return 1;
}
int dfs(int u,int T,int f)
{
    if(u==T)return f;
    int used=0;
    for(int &i=iter[u];i;i=next[i])
    {
        int v=to[i];
        if(level[v]==level[u]+1&&cap[i])
        {
            int w=dfs(v,T,min(cap[i],f-used));used+=w;
            if(w)
            {
                cap[i]-=w;cap[i^1]+=w;if(f==used)return f;
            }
        }
    }
    return used;
}
int dinic(int S,int T)
{
    int flow=0;
    while(1)
    {
        for(int i=0;i<=n*n+1;i++)iter[i]=h[i];
        if(!bfs(S,T))return flow;flow+=dfs(S,T,INF);
    }
}
int main()
{
    scanf("%d",&n);int S=0,T=n*n+1,tot=0;
    for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
    {
        int v;scanf("%d",&v);tot+=v;
        if(i%2==j%2){ins(get(i,j),T,v);ins(T,get(i,j),0);}
        else 
        {
            for(int k=0;k<4;k++)
            {
                int ii=i+x[k],jj=j+y[k];if(ii<1||ii>n||jj<1||jj>n)continue;
                ins(get(i,j),get(ii,jj),INF);ins(get(ii,jj),get(i,j),0);
            }
            ins(S,get(i,j),v);ins(get(i,j),S,0);
        }
    }
    cout<<tot-dinic(S,T);
    return 0;
 } 

[TYVJ1338] QQ农场

标签:++   ring   获得   oid   out   str   main   必须   top   

原文地址:http://www.cnblogs.com/lher/p/7581417.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!