题目链接:https://cn.vjudge.net/problem/HDU-1565

Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

Problem Description
给你一个n*n的格子的棋盘,每个格子里面有一个非负数。
从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的和最大。
 
Input
包括多个测试实例,每个测试实例包括一个整数n 和n*n个非负数(n<=20)
 
Output
对于每个测试实例,输出可能取得的最大的和
 
Sample Input
3
75 15 21
75 15 28
34 70 5
 
Sample Output
188

 

看了一下题目,立刻就想起来曾经好像在网络流专题里做过类似题目,

一翻博客,果然找到了这题的brother:http://www.cnblogs.com/dilthey/p/7401563.html

 

题解:

解法①:

既然,连这题的加强版 HDU 1569 - 方格取数 都可以用网络流做,这题当然也可以,代码几乎就是一点点修改:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<vector>
  4 #include<queue>
  5 #define MAX 405
  6 #define INF 0x3f3f3f3f
  7 #define id(i,j) (i-1)*n+j
  8 using namespace std;
  9 struct Edge{
 10     int u,v,c,f;
 11 };
 12 struct Dinic
 13 {
 14     int s,t;
 15     vector<Edge> E;
 16     vector<int> G[MAX];
 17     bool vis[MAX];
 18     int lev[MAX];
 19     int cur[MAX];
 20     void init(int l,int r)
 21     {
 22         E.clear();
 23         for(int i=l;i<=r;i++) G[i].clear();
 24     }
 25     void addedge(int from,int to,int cap)
 26     {
 27         E.push_back((Edge){from,to,cap,0});
 28         E.push_back((Edge){to,from,0,0});
 29         int m=E.size();
 30         G[from].push_back(m-2);
 31         G[to].push_back(m-1);
 32     }
 33     bool bfs()
 34     {
 35         memset(vis,0,sizeof(vis));
 36         queue<int> q;
 37         q.push(s);
 38         lev[s]=0;
 39         vis[s]=1;
 40         while(!q.empty())
 41         {
 42             int now=q.front(); q.pop();
 43             for(int i=0,_size=G[now].size();i<_size;i++)
 44             {
 45                 Edge edge=E[G[now][i]];
 46                 int nex=edge.v;
 47                 if(!vis[nex] && edge.c>edge.f)
 48                 {
 49                     lev[nex]=lev[now]+1;
 50                     q.push(nex);
 51                     vis[nex]=1;
 52                 }
 53             }
 54         }
 55         return vis[t];
 56     }
 57     int dfs(int now,int aug)
 58     {
 59         if(now==t || aug==0) return aug;
 60         int flow=0,f;
 61         for(int& i=cur[now],_size=G[now].size();i<_size;i++)
 62         {
 63             Edge& edge=E[G[now][i]];
 64             int nex=edge.v;
 65             if(lev[now]+1 == lev[nex] && (f=dfs(nex,min(aug,edge.c-edge.f)))>0)
 66             {
 67                 edge.f+=f;
 68                 E[G[now][i]^1].f-=f;
 69                 flow+=f;
 70                 aug-=f;
 71                 if(!aug) break;
 72             }
 73         }
 74         return flow;
 75     }
 76     int maxflow()
 77     {
 78         int flow=0;
 79         while(bfs())
 80         {
 81             memset(cur,0,sizeof(cur));
 82             flow+=dfs(s,INF);
 83         }
 84         return flow;
 85     }
 86 }dinic;
 87 int n,grid[23][23],sum;
 88 int d[4][2]={{0,+1},{+1,0},{0,-1},{-1,0}};
 89 bool inmap(int i,int j){return( 1<=i && i<=n && 1<=j && j<=n );}
 90 int main()
 91 {
 92     while(scanf("%d",&n)!=EOF)
 93     {
 94         dinic.init(0,n*n+1);
 95         dinic.s=0, dinic.t=n*n+1;
 96         sum=0;
 97         for(int i=1;i<=n;i++)
 98         {
 99             for(int j=1;j<=n;j++)
100             {
101                 scanf("%d",&grid[i][j]);
102                 sum+=grid[i][j];
103                 if((i+j)%2)
104                 {
105                     for(int k=0;k<4;k++) if(inmap(i+d[k][0],j+d[k][1])) dinic.addedge(id(i,j), id(i+d[k][0],j+d[k][1]), INF);
106                     dinic.addedge(dinic.s, id(i,j), grid[i][j]);
107                 }
108                 else dinic.addedge(id(i,j), dinic.t, grid[i][j]);
109             }
110         }
111         printf("%d\n",sum-dinic.maxflow());
112     }
113 }
View Code

相关文章: