2132: 圈地计划

Description

最近房地产商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求出一个收益最大的方案么?

Input

输入第一行为两个整数,分别为正整数N和M,分别表示区域的行数和列数;第2到N+1列,每行M个整数,表示商业区收益矩阵A;第N+2到2N+1列,每行M个整数,表示工业区收益矩阵B;第2N+2到3N+1行,每行M个整数,表示相邻额外收益矩阵C。第一行,两个整数,分别是n和m(1≤n,m≤100);

任何数字不超过1000”的限制

Output

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

Sample Input

3 3
1 2 3
4 5 6
7 8 9
9 8 7
6 5 4
3 2 1
1 1 1
1 3 1
1 1 1

Sample Output

81
【数据规模】
对于100%的数据有N,M≤100
 
最小割,转化为求最小代价,和球队收益差不多,但是点与点之间连流量等于c的双向边就好了,因为i和j相同损失的既有i的值也有j的值。
  1 #include<iostream>
  2 #include<cstdlib>
  3 #include<cmath>
  4 #include<cstring>
  5 #include<cstdio>
  6 #include<algorithm>
  7 #include<string>
  8 #include<map>
  9 #include<queue>
 10 #include<vector>
 11 #include<set>
 12 #define inf 1000000000
 13 #define maxn 100000+5
 14 #define maxm 500000+5
 15 #define eps 1e-10
 16 #define ll long long
 17 #define for0(i,n) for(int i=0;i<=(n);i++)
 18 #define for1(i,n) for(int i=1;i<=(n);i++)
 19 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
 20 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
 21 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go)
 22 using namespace std;
 23 int read(){
 24     int x=0,f=1;char ch=getchar();
 25     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 26     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
 27     return x*f;
 28 }
 29 int n,m,s,t,maxflow,tot=1,cnt,head[maxn],cur[maxn],h[maxn],q[maxn];
 30 int mx[4]={0,0,1,-1},my[4]={1,-1,0,0};
 31 struct edge{
 32     int go,next,w;
 33 }e[2*maxm];
 34 void insert(int u,int v,int w){
 35     e[++tot]=(edge){v,head[u],w};head[u]=tot;
 36     e[++tot]=(edge){u,head[v],0};head[v]=tot;
 37 }
 38 void ins(int u,int v,int w){
 39     e[++tot]=(edge){v,head[u],w};head[u]=tot;
 40     e[++tot]=(edge){u,head[v],w};head[v]=tot;
 41 }
 42 bool bfs(){
 43     for0(i,t)h[i]=-1;
 44     h[s]=0;q[1]=s;int l=0,r=1;
 45     while(l!=r){
 46         int x=q[++l];
 47         for4(i,x)
 48             if(e[i].w&&h[y]==-1)
 49                 h[y]=h[x]+1,q[++r]=y;
 50     }
 51     return h[t]!=-1;
 52 }
 53 int dfs(int x,int f){
 54     if(x==t)return f;
 55     int tmp=0,used=0;
 56     for4(i,x)
 57         if(e[i].w&&h[y]==h[x]+1){
 58             tmp=dfs(y,min(e[i].w,f-used));
 59             e[i].w-=tmp;if(e[i].w)cur[x]=i;
 60             e[i^1].w+=tmp;used+=tmp;
 61             if(used==f)return f;
 62         }
 63     if(!used)h[x]=-1;
 64     return used;
 65 }
 66 void dinic(){
 67     maxflow=0;
 68     while(bfs()){
 69         for0(i,t)cur[i]=head[i];
 70         maxflow+=dfs(s,inf);
 71     }
 72 }
 73 int main(){
 74     //freopen("input.txt","r",stdin);
 75     //freopen("output.txt","w",stdout);
 76     n=read();m=read();s=n*m+1;t=s+1;int ans=0;
 77     for1(i,n)
 78         for1(j,m){
 79             int x=read();ans+=x;
 80             if((i+j)&1)insert(s,(i-1)*m+j,x);
 81             else insert((i-1)*m+j,t,x);
 82         }
 83     for1(i,n)
 84         for1(j,m){
 85             int x=read();ans+=x;
 86             if(~(i+j)&1)insert(s,(i-1)*m+j,x);
 87             else insert((i-1)*m+j,t,x);
 88         }
 89     for1(i,n)
 90         for1(j,m){
 91             int x=read();
 92             for0(k,3){  
 93                 int xx=i+mx[k];  
 94                 int yy=j+my[k];  
 95                 if(xx<=0||yy<=0||xx>n||yy>m)continue;  
 96                 ans+=x;  
 97                 ins((i-1)*m+j,(xx-1)*m+yy,x);
 98             }  
 99         }
100     dinic();
101     printf("%d\n",ans-maxflow);
102     return 0;
103 }
View Code

 

 
posted @ 2016-07-18 18:42  HTWX  阅读(97)  评论(0编辑  收藏  举报