• 【2011集训队出题】圈地计划


    题目

      最近房地产商GDOI(Group of Dumbbells Or Idiots)从NOI(Nuts Old Idiots)手中得到了一块开发土地。据了解,这块土地是一块矩形的区域,可以纵横划分为N×M块小区域。GDOI要求将这些区域分为商业区和工业区来开发。根据不同的地形环境,每块小区域建造商业区和工业区能取得不同的经济价值。更具体点,对于第i行第j列的区域,建造商业区将得到Aij收益,建造工业区将得到Bij收益。另外不同的区域连在一起可以得到额外的收益,即如果区域(I,j)相邻(相邻是指两个格子有公共边)有K块(显然K不超过4)类型不同于(I,j)的区域,则这块区域能增加k×Cij收益。经过Tiger.S教授的勘察,收益矩阵A,B,C都已经知道了。你能帮GDOI求出一个收益最大的方案么?

    分析

    二元关系,最小割。
    先把总收益求出来,在减去最小割。
    连边,对于两个相邻的点x,y。
    源点点S向x连a[x]的边,向y连b[y]的边。
    x向汇点T连b[x]的边,y向汇点T连a[y]的边。
    x、y之间连c[x]+c[y]的双向边。

    #include <cmath>
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    const long long maxlongint=2147483647;
    const long long mo=1000000007;
    const long long N=10010;
    using namespace std;
    long long next[N*7],last[N*7],to[N*7],up[N*7],n,m,d[N*10],dis[N],tot;
    long long f[N*7],ans,c[111][111];
    long long zz[4][2]=
    {
     {0,1},
     {1,0},
     {0,-1},
     {-1,0}
    };
    long long bj(long long x,long long y,long long z)
    {
    	next[++tot]=last[x];
    	last[x]=tot;
    	to[tot]=y;
    	f[tot]=z;
    	next[++tot]=last[y];
    	last[y]=tot;
    	to[tot]=x;
    	f[tot]=0;
    }
    bool bfs()
    {
    	memset(dis,0,sizeof(dis));
    	d[1]=0;
    	dis[0]=1;
    	long long head=0,tail=1,k;
    	while(head<tail)
    	{
    		k=d[++head];
    		for(long long i=last[k];i;i=next[i])
    		{
    			long long j=to[i];
    			if(f[i]>0 && !dis[j])
    			{
    				d[++tail]=j;
    				dis[j]=dis[k]+1;
    			}
    		}
    	}
    	return dis[n*m+m];
    }
    long long aug(long long x,long long y)
    {
    	if(x==n*m+m) return y;
    	long long cross=0;
    	for(long long i=last[x];i;i=next[i])
    	{
    		long long j=to[i];
    		if(dis[x]+1==dis[j] && f[i]>0)
    		{
    			long long o=aug(j,min(y,f[i]));
    			if(o>0)
    			{
    				y-=o;
    				f[i]-=o;
    				f[i^1]+=o;
    				cross+=o;
    			}
    		}
    	}
    	return cross;
    }
    int main()
    {
    	scanf("%lld%lld",&n,&m);
    	tot=1;
    	for(long long i=1;i<=n;i++)
    		for(long long j=1;j<=m;j++)
    		{
    			long long pos=(i-1)*m+j;
    			long long x;
    			scanf("%lld",&x);
    			ans+=x;
    			if(i%2 && j%2 || i%2==0 && j%2==0) bj(0,pos,x);
    			else bj(pos,n*m+m,x);
    		}
    	for(long long i=1;i<=n;i++)
    		for(long long j=1;j<=m;j++)
    		{
    			long long pos=(i-1)*m+j;
    			long long x;
    			scanf("%lld",&x);
    			ans+=x;
    			if(i%2 && j%2 || i%2==0 && j%2==0) bj(pos,n*m+m,x);
    			else bj(0,pos,x);
    		}
    	for(long long i=1;i<=n;i++)
    		for(long long j=1;j<=m;j++)
    			scanf("%lld",&c[i][j]);
    	for(long long i=1;i<=n;i++)
    		for(long long j=1;j<=m;j++)
    			for(long long k=0;k<=3;k++)
    			{
    				long long xx=i+zz[k][0],yy=j+zz[k][1];
    				if(xx<1 || yy<1 || xx>n || yy>m) continue;
    				long long pos=(i-1)*m+j,pos1=(xx-1)*m+yy;
    				bj(pos,pos1,c[i][j]+c[xx][yy]);
    				ans+=c[i][j];
    			}
    	while(bfs())
    		ans-=aug(0,maxlongint);
    	cout<<ans<<endl;
    }
    
  • 相关阅读:
    如何将网格式报表打印成其它样式
    拥有与实力不相称的脾气是种灾难——北漂18年(23)
    8.8.1 Optimizing Queries with EXPLAIN
    mysql 没有rowid 怎么实现根据rowid回表呢?
    secondary index
    8.5.5 Bulk Data Loading for InnoDB Tables 批量数据加载
    mysql 中key 指的是索引
    8.5.4 Optimizing InnoDB Redo Logging 优化InnoDB Redo 日志
    8.5.3 Optimizing InnoDB Read-Only Transactions 优化InnoDB 只读事务
    8.5.1 Optimizing Storage Layout for InnoDB Tables InnoDB表的存储布局优化
  • 原文地址:https://www.cnblogs.com/chen1352/p/9066578.html
Copyright © 2020-2023  润新知