codevs1907 方格取数 3

«问题描述:
在一个有m*n 个方格的棋盘中,每个方格中有一个正整数。现要从方格中取数,使任
意2 个数所在方格没有公共边,且取出的数的总和最大。试设计一个满足要求的取数算法。
«编程任务:
对于给定的方格棋盘,按照取数要求编程找出总和最大的数。

输入描述 Input Description

第1 行有2 个正整数m和n,分别表示棋盘的行数
和列数。接下来的m行,每行有n个正整数,表示棋盘方格中的数。

输出描述 Output Description

将取数的最大总和输出

样例输入 Sample Input

3 3
1 2 3
3 2 3
2 3 1

样例输出 Sample Output

11

数据范围及提示 Data Size & Hint

n,m<=30

 

正解:网络流

解题报告:

  同HDU1565,我的题解的传送门:http://www.cnblogs.com/ljh2000-jump/p/5756667.html

 

 1 //It is made by jump~
 2 #include <iostream>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <cstdio>
 6 #include <cmath>
 7 #include <algorithm>
 8 #include <ctime>
 9 #include <vector>
10 #include <queue>
11 #include <map>
12 #include <set>
13 #ifdef WIN32   
14 #define OT "%I64d"
15 #else
16 #define OT "%lld"
17 #endif
18 using namespace std;
19 typedef long long LL;
20 const int MAXN = 501;
21 const int MAXM = 500011;
22 const int inf = (1<<30);
23 int m,n,sum,S,T,ecnt,ans;
24 int a[MAXN][MAXN],deep[MAXN*MAXN];
25 int first[MAXN*MAXN];
26 queue<int>Q;
27 struct edge{
28     int next,to,f;
29 }e[MAXM];
30 
31 inline int getint()
32 {
33        int w=0,q=0;
34        char c=getchar();
35        while((c<'0' || c>'9') && c!='-') c=getchar();
36        if (c=='-')  q=1, c=getchar();
37        while (c>='0' && c<='9') w=w*10+c-'0', c=getchar();
38        return q ? -w : w;
39 }
40 
41 inline void link(int x,int y,int z){
42     e[++ecnt].next=first[x]; first[x]=ecnt; e[ecnt].to=y; e[ecnt].f=z;
43     e[++ecnt].next=first[y]; first[y]=ecnt; e[ecnt].to=x; e[ecnt].f=0;
44 }
45 
46 inline bool bfs(){
47     while(!Q.empty()) Q.pop();
48     for(int i=1;i<=T;i++) deep[i]=0;
49     Q.push(S); deep[S]=1;
50     while(!Q.empty()) {
51     int u=Q.front(); Q.pop();
52     for(int i=first[u];i;i=e[i].next) {
53         int v=e[i].to;
54         if(e[i].f && !deep[v]) deep[v]=deep[u]+1,Q.push(v);
55     }
56     }
57     if(deep[T]!=0) return true;
58     return false;
59 }
60 
61 inline int Dinic(int x,int remain){
62     if(remain==0 || x==T) return remain;
63     int f,flow=0;
64     for(int i=first[x];i;i=e[i].next) {
65     int v=e[i].to;
66     if(e[i].f && deep[v]==deep[x]+1){
67         f=Dinic(v,min(remain,e[i].f));
68         if(f){
69         flow+=f; e[i].f-=f; e[i^1].f+=f;
70         remain-=f; if(remain==0) return flow;
71         } else deep[v]=-1;
72     }
73     }
74     return flow;
75 }
76 
77 inline void work(){
78     m=getint(); n=getint();
79     for(int i=1;i<=m;i++) for(int j=1;j<=n;j++)   a[i][j]=getint(),sum+=a[i][j];
80     S=m*n+1;T=S+1; ecnt=1;
81     for(int i=1;i<=m;i++) for(int j=1;j<=n;j++) if((i+j)%2==0) link(S,(i-1)*n+j,a[i][j]); else link((i-1)*n+j,T,a[i][j]);//黑白染色
82     for(int i=1;i<=m;i++) 
83     for(int j=1;j<=n;j++){
84         if((i+j)%2) continue;
85         if(i!=1) link((i-1)*n+j,(i-2)*n+j,inf);     
86         if(j!=1) link((i-1)*n+j,(i-1)*n+j-1,inf);
87         if(j!=n) link((i-1)*n+j,(i-1)*n+j+1,inf);
88         if(i!=m) link((i-1)*n+j,i*n+j,inf);
89     }
90     while(bfs()) ans+=Dinic(S,inf);
91     printf("%d",sum-ans);
92 }
93 
94 int main()
95 {
96   work();
97   return 0;
98 }

 

posted @ 2016-08-10 14:51  ljh_2000  阅读(186)  评论(0编辑  收藏  举报