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
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
【数据规模】
对于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 }