• 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 }
  • 相关阅读:
    16进制字符串的转换
    UINavigationBar统一修改导航条样式
    3D touch
    WKWebView
    CAEmitterLayer 粒子效果(发射器)
    SDWebImage下载图片的使用
    PHP之string之str_shuffle()函数使用
    Redis之hiredis API (String)
    Redis之数据类型Sting字符串
    PHP之string之str_repeat()函数使用
  • 原文地址:https://www.cnblogs.com/Yuzao/p/7222567.html
Copyright © 2020-2023  润新知