zoukankan      html  css  js  c++  java
  • 【网络流24题----09】方格取数问题

    «问题描述:
    在一个有m*n 个方格的棋盘中,每个方格中有一个正整数。现要从方格中取数,使任
    意2 个数所在方格没有公共边,且取出的数的总和最大。试设计一个满足要求的取数算法。
    «编程任务:
    对于给定的方格棋盘,按照取数要求编程找出总和最大的数。
    «数据输入:
    由文件grid.in提供输入数据。文件第1 行有2 个正整数m和n,分别表示棋盘的行数
    和列数。接下来的m行,每行有n个正整数,表示棋盘方格中的数。
    «结果输出:
    程序运行结束时,将取数的最大总和输出到文件grid.out中。
    输入文件示例 输出文件示例
    grid.in
    3 3
      1 2 3

    3 2 3

    2 3 1

    grid.out

    11

    (1<=N,M<=30)


    对于棋盘黑白染色构出一张二分图,二分图最大独立集。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<algorithm>
      4 #include<vector>
      5 #include<cstdlib>
      6 #include<cmath>
      7 #include<cstring>
      8 using namespace std;
      9 #define maxn 910
     10 #define inf 0x7fffffff
     11 #define llg int 
     12 #define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
     13 llg n,m,e[maxn],N,p[10][5],g[50][50],k,tot,se[50][50];
     14 
     15 struct DINIC
     16 {
     17     vector<llg>a[maxn],ba[maxn],val[maxn];
     18     llg dl[maxn],deep[maxn],bj[maxn];
     19 
     20     void insert(llg x,llg y,llg z)
     21     {
     22         a[x].push_back(y),val[x].push_back(z);
     23         a[y].push_back(x),val[y].push_back(0);
     24         ba[x].push_back(a[y].size()-1); ba[y].push_back(a[x].size()-1);
     25     }
     26 
     27     llg dfs(llg x,llg low)
     28     {
     29         llg va=0,inc=0;
     30         if (x==N) return low;
     31         llg w=a[x].size();
     32         for (llg i=0;i<w;i++)
     33             if (deep[x]+1==deep[a[x][i]] && val[x][i]>0 && (va=dfs(a[x][i],min(low,val[x][i]))))
     34             {
     35                 val[x][i]-=va; val[a[x][i]][ba[x][i]]+=va; inc+=va;
     36                 return va;
     37             }
     38         if (!inc) deep[x]=-1;
     39         return 0;
     40     }
     41 
     42     void fencen()
     43     {
     44         llg x,w,v; deep[0]=0;
     45         memset(bj,0,sizeof(bj));
     46         llg head=0,tail=1; dl[1]=0; bj[0]=1;
     47         do
     48         {
     49             x=dl[++head]; w=a[x].size();
     50             for (llg i=0;i<w;i++)
     51             {
     52                 v=a[x][i];
     53                 if (bj[v] || val[x][i]<=0) continue;
     54                 dl[++tail]=v;
     55                 deep[v]=deep[x]+1; bj[v]=1;
     56             }
     57         }while (head!=tail);
     58     }
     59 
     60     llg dinic()
     61     {
     62         llg ans=0;
     63         while (1)
     64         {
     65             fencen();
     66             if (!bj[N]) break;
     67             ans+=dfs(0,inf);
     68         }
     69         return ans;
     70     }
     71 
     72     void oupt()
     73     {
     74         for (llg i=1;i<=k;i++)
     75         {
     76             printf("%d: ",i);
     77             llg w=a[i].size();
     78             for (llg e=0;e<w;e++)
     79             {
     80                 llg v=a[i][e];
     81                 if (v>k && v<N && val[i][e]==0) printf("%d ",v-k); 
     82             }
     83             printf("
    ");
     84         }
     85     }
     86 }G;
     87 
     88 llg ma(llg x,llg y) {return x*m-m+y;}
     89 
     90 void init()
     91 {
     92     p[1][1]=1,p[2][1]=-1,p[3][2]=1,p[4][2]=-1;
     93     cin>>n>>m;
     94     N=n*m+1;
     95     for (llg i=1;i<=n;i++)
     96         for (llg j=1;j<=m;j++)
     97             scanf("%d",&g[i][j]),tot+=g[i][j];
     98     for (llg i=1;i<=n;i++)
     99         for (llg j=1;j<=m;j++)
    100         {
    101             for (llg k=1;k<=4;k++)
    102                 {
    103                     llg x=i+p[k][1],y=j+p[k][2];
    104                     if (x>n || x<1 || y>m || y<1) continue;
    105                     se[x][y]=(se[i][j]+1)%2;
    106                 }
    107         }
    108     for (llg i=1;i<=n;i++)
    109         for (llg j=1;j<=m;j++)
    110             if (se[i][j])
    111             {
    112                 for (llg k=1;k<=4;k++)
    113                 {
    114                     llg x=i+p[k][1],y=j+p[k][2];
    115                     if (x>n || x<1 || y>m || y<1) continue;
    116                     G.insert(ma(i,j),ma(x,y),inf);
    117                 }
    118                 G.insert(0,ma(i,j),g[i][j]);
    119             }
    120     for (llg i=1;i<=n;i++)
    121         for (llg j=1;j<=m;j++)
    122             if (!se[i][j])
    123                 G.insert(ma(i,j),N,g[i][j]);
    124 }
    125 
    126 int main()
    127 {
    128     yyj("grid");
    129     init();
    130     cout<<tot-G.dinic();
    131     return 0;
    132 }
    本文作者:xrdog 作者博客:http://www.cnblogs.com/Dragon-Light/ 转载请注明出处,侵权必究,保留最终解释权!
  • 相关阅读:
    不足百行代码 实体数组转DataTable通用类
    【翻译】WEB安全设计规范(4.1)
    也为读者说几句(兼为什么要骂烂书译者)
    重用之前应仔细分析问题用错轮子有感
    最长代码有多长:不符[单一职责原则(SRP)]的常见设计
    "千里之堤毁于蚁穴"重点项目不能交付之谜(一)泥淖中的验收测试
    企业快速开发框架基于配置文件
    从面试题看高级软件工程师需要哪些技艺
    面试英语【转】
    测试
  • 原文地址:https://www.cnblogs.com/Dragon-Light/p/6357781.html
Copyright © 2011-2022 走看看