最近房地产商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求出一个收益最大的方案么?
输入第一行为两个整数,分别为正整数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”的限制
1 #include<cstdio>
2 #include<cstring>
3 const int maxn=300;
4 const int maxm=maxn*maxn*5;
5 inline int min_(int x,int y){return x<y?x:y;}
6 inline int swap_(int&x,int&y){x^=y,y^=x,x^=y;}
7 int n,m,s,t,ans;
8 int a;
9 int ind[maxn][maxn],bus[maxn][maxn],com[maxn][maxn];
10 int h[maxm],hs=1,et[maxm],ew[maxm],en[maxm];
11 void add(int u,int v,int w){++hs,et[hs]=v,ew[hs]=w,en[hs]=h[u],h[u]=hs;}
12 int nh,nl;
13 int hb[]={-1,0,1,0};
14 int lb[]={0,1,0,-1};
15 int q[maxm],head,tail;
16 int d[maxm];
17 void bfs(){
18 memset(d,0,sizeof(d));
19 head=tail=0;
20 q[head++]=s,d[s]=1;
21 while(head>tail){
22 a=q[tail++];
23 for(int i=h[a];i;i=en[i])
24 if(!d[et[i]]&&ew[i]){
25 d[et[i]]=d[a]+1;
26 if(et[i]==t) return;
27 q[head++]=et[i];
28 }
29 }
30 }
31 int ap(int k,int w){
32 if(k==t) return w;
33 int dw=w;
34 for(int i=h[k];i&&dw;i=en[i])
35 if(ew[i]&&d[et[i]]==d[k]+1){
36 int wt=ap(et[i],min_(w,ew[i]));
37 if(wt) ew[i]-=wt,ew[i^1]+=wt,dw-=wt;
38 else d[et[i]]=0;
39 }
40 return w-dw;
41 }
42 void Dinic(){while(bfs(),d[t]) ans-=ap(s,1e9);}
43 int main(){
44 freopen("nt2011_land.in","r",stdin);
45 freopen("nt2011_land.out","w",stdout);
46 scanf("%d%d",&n,&m);
47 s=0,t=1;
48 for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&ind[i][j]);
49 for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&bus[i][j]);
50 for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&com[i][j]);
51 for(int i=1;i<=n;i++)
52 for(int j=1;j<=m;j++){
53 if((i^j)&1) swap_(ind[i][j],bus[i][j]);
54 add(s,i*m+j,ind[i][j]),add(i*m+j,s,0);
55 add(i*m+j,t,bus[i][j]),add(t,i*m+j,0);
56 ans=ans+ind[i][j]+bus[i][j];
57 if((i^j)&1) for(int k=0;k<4;k++){
58 nh=i+hb[k],nl=j+lb[k];
59 a=com[i][j]+com[nh][nl];
60 if(nh&&nh<=n&&nl&&nl<=m){
61 add(i*m+j,nh*m+nl,a);
62 add(nh*m+nl,i*m+j,a);
63 ans+=a;
64 }
65 }
66 }
67 Dinic();
68 printf("%d",ans);
69 return 0;
70 }