zoukankan      html  css  js  c++  java
  • bzoj2132: 圈地计划

    2132: 圈地计划

    Time Limit: 2 Sec  Memory Limit: 256 MB
    Submit: 1072  Solved: 493
    [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

    Sample Output

    81
    【数据规模】
    对于100%的数据有N,M≤100

    HINT

     数据已加强,并重测--2015.5.15

     
     
    这题那时候一脸懵逼完全不会写最后滚去看了Po大爷的题解..
    QAQ广东省选神题好多...我吃枣药丸.. 
    转自 PoPoQQQ: 

    普通的最小割建图会遇到一个问题:

    割断两块之间的边收益为正,即代价为负

    因此我们如果正常建最小割,那么两块之间的边权就会是负的

    那么我们将这个矩阵黑白染色,将白格ST反向

    这样割断两块之间的连边相当于两块选择了同一用途,代价为正

    就可以正常跑了

    (这个反转感觉挺6的...或者是我脑洞太小?)

     1 #include<bits/stdc++.h>
     2 #define inf 2147483647
     3 #define N 1280
     4 #define rep(i,l,r) for(int i=l;i<=r;i++)
     5 using namespace std;
     6 const int x[4]={1,0,0,-1};
     7 const int y[4]={0,1,-1,0};
     8 int T,head[N*10<<1],cnt,ans,ccz,n,tot=1,mp[N][N],dis[N*10<<1],num[N][N],m,a[N][N],b[N][N],nowx,nowy;
     9 struct node{
    10     int to,next,w;
    11 }e[2000000];
    12 inline bool bfs(){
    13      for(int i=0;i<=T;i++) dis[i]=-1; queue<int>q; q.push(0); dis[0]=0;
    14      while(!q.empty()) {
    15           int x=q.front(); q.pop();
    16           for(int k=head[x];k;k=e[k].next) 
    17              if(dis[e[k].to]<0 && e[k].w>0) {
    18                    dis[e[k].to]=dis[x]+1; q.push(e[k].to);
    19              }
    20      }
    21      if(dis[T]>0) return 1;else return 0;
    22 }
    23 int find(int x,int low){
    24      if(x==T) return low;
    25      int delta=low,now;
    26      for(int k=head[x];k;k=e[k].next) 
    27        if(e[k].w>0 && dis[e[k].to]==dis[x]+1){ 
    28            now=find(e[k].to,min(e[k].w,delta));
    29            e[k].w-=now; e[k^1].w+=now;   delta-=now;
    30            if(!delta) return low;
    31         } 
    32      dis[x]=-1;
    33      return low-delta;
    34 }
    35 inline void ins(int u,int v,int w) {
    36      e[++tot].to=v; e[tot].next=head[u]; head[u]=tot; e[tot].w=w;
    37 }
    38 inline void insert(int u,int v,int w) {
    39      ins(u,v,w); ins(v,u,0);
    40 }
    41 int main () { 
    42      scanf("%d%d",&n,&m);
    43      rep(i,1,n) rep(j,1,m) scanf("%d",&a[i][j]),ans+=a[i][j];
    44      rep(i,1,n) rep(j,1,m) scanf("%d",&b[i][j]),ans+=b[i][j];
    45      rep(i,1,n) rep(j,1,m) scanf("%d",&mp[i][j]);
    46      rep(i,1,n) rep(j,1,m) num[i][j]=++cnt;T=cnt+1;
    47      rep(i,1,n) rep(j,1,m) if((i+j)&1) {
    48           insert(0,num[i][j],a[i][j]); insert(num[i][j],T,b[i][j]);
    49      } else insert(0,num[i][j],b[i][j]),insert(num[i][j],T,a[i][j]);
    50      rep(i,1,n) rep(j,1,m) rep(k,0,3) {
    51           nowx=i+x[k]; nowy=j+y[k];
    52           if(nowx<1||nowx>n||nowy<1||nowy>m) continue;
    53           ans+=mp[i][j];     
    54           insert(num[i][j],num[nowx][nowy],mp[i][j]+mp[nowx][nowy]);
    55      }
    56      while(bfs()) ans-=find(0,inf);
    57      printf("%d",ans);
    58 }
    View Code
  • 相关阅读:
    机器学习项目实战----信用卡欺诈检测(二)
    机器学习项目实战----信用卡欺诈检测(一)
    机器学习之使用Python完成逻辑回归
    逻辑回归算法
    机器学习之梯度下降
    线性回归算法原理推导
    Spark之RDD容错原理及四大核心要点
    Spark之RDD依赖关系及DAG逻辑视图
    Spark之RDD弹性特性
    Spark之RDD的定义及五大特性
  • 原文地址:https://www.cnblogs.com/Bloodline/p/5886380.html
Copyright © 2011-2022 走看看