zoukankan      html  css  js  c++  java
  • bzoj 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
     
    题解:
    类似于为了博多一题,同为总和减不合法,此题唯一变换就是不同改为相同,所以只需调换顺序即可
    但是此题对于我这种蒟蒻来说,需要get新技能哈,怎么保证相邻连起来不矛盾呢?
    这里用到二分图染色,对于网格图的都普遍用到此法....然后就直接黑向白或者白向黑连边即可.
     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <cmath>
     6 #define id(x,y) (((x)-1)*m+(y))
     7 using namespace std;
     8 const int N=105,P=100005,M=2000005,inf=2e9;
     9 int map[N][N],n,m;bool color[N][N];
    10 int head[P],num=1;
    11 struct Lin{
    12     int next,to,dis;
    13 }a[M];
    14 void makecolor(int x,int y)
    15 {
    16     int k=color[x][y]^1;
    17     if(x<n && !color[x+1][y])color[x+1][y]=k,makecolor(x+1,y);
    18     if(y<m && !color[x][y+1])color[x][y+1]=k,makecolor(x,y+1);
    19 }
    20 void init(int x,int y,int dis){
    21     a[++num].next=head[x];a[num].to=y;a[num].dis=dis;head[x]=num;
    22 }
    23 void addedge(int x,int y,int dis){
    24     init(x,y,dis);init(y,x,0);
    25 }
    26 int S=0,T,dep[P],q[P];
    27 bool bfs(){
    28     memset(dep,0,sizeof(dep));
    29     int t=0,sum=1,u,x;
    30     dep[S]=1;q[1]=S;
    31     while(t!=sum){
    32         x=q[++t];
    33         for(int i=head[x];i;i=a[i].next){
    34             u=a[i].to;
    35             if(a[i].dis<=0 || dep[u])continue;
    36             dep[u]=dep[x]+1;q[++sum]=u;
    37         }
    38     }
    39     return dep[T];
    40 }
    41 int dfs(int x,int flow){
    42     if(x==T || !flow)return flow;
    43     int tot=0,u,tmp;
    44     for(int i=head[x];i;i=a[i].next){
    45         u=a[i].to;
    46         if(dep[u]!=dep[x]+1 || a[i].dis<=0)continue;
    47         tmp=dfs(u,min(flow,a[i].dis));
    48         a[i].dis-=tmp;a[i^1].dis+=tmp;
    49         tot+=tmp;flow-=tmp;
    50         if(!flow)break;
    51       }
    52     if(!tot)dep[x]=0;
    53     return tot;
    54 }
    55 int maxflow(){
    56     int tot=0,tmp;
    57     while(bfs()){
    58         tmp=dfs(S,inf);
    59         while(tmp)tot+=tmp,tmp=dfs(S,inf);
    60     }
    61     return tot;
    62 }
    63 int main()
    64 {
    65     scanf("%d%d",&n,&m);T=n*m+1;
    66     color[1][1]=true;makecolor(1,1);
    67     int x,ans=0;
    68     for(int i=1;i<=n;i++)
    69     for(int j=1;j<=m;j++){
    70         scanf("%d",&x);ans+=x;
    71         if(color[i][j])addedge(S,id(i,j),x);
    72         else addedge(id(i,j),T,x);
    73     }
    74     for(int i=1;i<=n;i++)
    75     for(int j=1;j<=m;j++){
    76         scanf("%d",&x);ans+=x;
    77         if(!color[i][j])addedge(S,id(i,j),x);
    78         else addedge(id(i,j),T,x);
    79     }
    80     for(int i=1;i<=n;i++)
    81     for(int j=1;j<=m;j++)
    82     scanf("%d",&map[i][j]),ans+=(map[i][j]<<2);
    83     for(int i=1;i<=n;i++)
    84         for(int j=1;j<=m;j++){
    85             if(color[i][j]){
    86                 if(j>1)addedge(id(i,j-1),id(i,j),map[i][j]+map[i][j-1]),addedge(id(i,j),id(i,j-1),map[i][j]+map[i][j-1]);
    87                 if(i>1)addedge(id(i-1,j),id(i,j),map[i][j]+map[i-1][j]),addedge(id(i,j),id(i-1,j),map[i][j]+map[i-1][j]);
    88                 if(i<n)addedge(id(i+1,j),id(i,j),map[i][j]+map[i+1][j]),addedge(id(i,j),id(i+1,j),map[i][j]+map[i+1][j]);
    89                 if(j<m)addedge(id(i,j+1),id(i,j),map[i][j]+map[i][j+1]),addedge(id(i,j),id(i,j+1),map[i][j]+map[i][j+1]);
    90             }
    91         }
    92     for(int i=1;i<=m;i++)ans-=map[1][i]+map[n][i];
    93     for(int i=1;i<=n;i++)ans-=map[i][1]+map[i][m];
    94     ans=ans-maxflow();
    95     printf("%d
    ",ans);
    96     return 0;
    97 }
  • 相关阅读:
    手机号码正则表达式
    POJ 3233 Matrix Power Series 矩阵快速幂
    UVA 11468
    UVA 1449
    HDU 2896 病毒侵袭 AC自动机
    HDU 3065 病毒侵袭持续中 AC自动机
    HDU 2222 Keywords Search AC自动机
    POJ 3461 Oulipo KMP模板题
    POJ 1226 Substrings KMP
    UVA 1455 Kingdom 线段树+并查集
  • 原文地址:https://www.cnblogs.com/Yuzao/p/7222567.html
Copyright © 2011-2022 走看看