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
  • 相关阅读:
    C# 不用添加WebService引用,调用WebService方法
    贪心 & 动态规划
    trie树 讲解 (转载)
    poj 2151 Check the difficulty of problems (检查问题的难度)
    poj 2513 Colored Sticks 彩色棒
    poj1442 Black Box 栈和优先队列
    啦啦啦
    poj 1265 Area(pick定理)
    poj 2418 Hardwood Species (trie树)
    poj 1836 Alignment 排队
  • 原文地址:https://www.cnblogs.com/Bloodline/p/5886380.html
Copyright © 2011-2022 走看看