2132: 圈地计划
Time Limit: 2 Sec Memory Limit: 256 MBSubmit: 808 Solved: 362
[ Submit][ Status][ Discuss]
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
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
解题思路:和2172简直一模一样,不过相邻的两条边,要将商业边和工业边反过来,
可以黑白染色,然后建边,最后最大流就可以了。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 10100
#define P(x,y) ((x)*n-n+(y))
#define S 0
#define T (m*n+1)
#define INF 0x3f3f3f3f
using
namespace
std;
int
m,n,ans;
const
int
dx[]={1,-1,0,0};
const
int
dy[]={0,0,1,-1};
namespace
Max_Flow{
struct
abcd{
int
to,f,next;
}table[1001001];
int
head[M],tot=1;
int
dpt[M];
void
Add(
int
x,
int
y,
int
z)
{
table[++tot].to=y;
table[tot].f=z;
table[tot].next=head[x];
head[x]=tot;
}
void
Link(
int
x,
int
y,
int
z)
{
Add(x,y,z);
Add(y,x,z);
}
bool
BFS()
{
static
int
q[M];
int
i,r=0,h=0;
memset
(dpt,-1,
sizeof
dpt);
dpt[S]=1;q[++r]=S;
while
(r!=h)
{
int
x=q[++h];
for
(i=head[x];i;i=table[i].next)
if
(table[i].f&&!~dpt[table[i].to])
{
dpt[table[i].to]=dpt[x]+1;
q[++r]=table[i].to;
if
(table[i].to==T)
return
true
;
}
}
return
false
;
}
int
Dinic(
int
x,
int
flow)
{
int
i,left=flow;
if
(x==T)
return
flow;
for
(i=head[x];i&&left;i=table[i].next)
if
(table[i].f&&dpt[table[i].to]==dpt[x]+1)
{
int
temp=Dinic(table[i].to,min(left,table[i].f) );
left-=temp;
table[i].f-=temp;
table[i^1].f+=temp;
}
if
(left) dpt[x]=-1;
return
flow-left;
}
}
int
main()
{
using
namespace
Max_Flow;
int
i,j,k,x;
cin>>m>>n;
for
(i=1;i<=m;i++)
for
(j=1;j<=n;j++)
{
scanf
(
"%d"
,&x);
ans+=x;
if
(i+j&1)
Link(S,P(i,j),x);
else
Link(P(i,j),T,x);
}
for
(i=1;i<=m;i++)
for
(j=1;j<=n;j++)
{
scanf
(
"%d"
,&x);
ans+=x;
if
(~(i+j)&1)
Link(S,P(i,j),x);
else
Link(P(i,j),T,x);
}
for
(i=1;i<=m;i++)
for
(j=1;j<=n;j++)
{
scanf
(
"%d"
,&x);
for
(k=0;k<4;k++)
{
int
xx=i+dx[k];
int
yy=j+dy[k];
if
(xx<=0||yy<=0||xx>m||yy>n)
continue
;
ans+=x;
Link(P(i,j),P(xx,yy),x);
}
}
while
( BFS() )
ans-=Dinic(S,INF);
cout<<ans<<endl;
return
0;
}