[CODEVS 1907]方格取数 3
【问题描述】
在一个有m*n个方格的棋盘中,每个方格中有一个正整数。现要从方格中取数,使任意2 个数所在方格没有公共边,且取出的数的总和最大。试设计一个满足要求的取数算法。
对于给定的方格棋盘,按照取数要求编程找出总和最大的数。
【输入】
第1行有2个正整数m和n,分别表示棋盘的行数和列数。
接下来的m行,每行有n个正整数,表示棋盘方格中的数。
【输出】
将取数的最大总和输出。
【算法分析】
自从理解最大流之后,sjj118的最大流算法代码已经成为模板了。
对整个矩阵进行黑白染色,每个黑点分别指向相邻的白点,容量为+∞,建立超级源节点s指向所有黑点,容量为a[i][j];建立超级汇点t使所有白点指向它,容量亦为a[i][j]。
计算新图的最小割,此时图中不存在路径s~t,也就是不存在相邻两格的数,并且保证剩余有限容量边的容量总和最大。
所以答案就是上述的容量总和,输出sum-maxflow即可。
【程序代码】
1 #include<cstdio> 2 #include<algorithm> 3 #define maxn 10000 4 #define inf 1000000 5 using namespace std; 6 int n,m,a[40][40],ans=0,num=0; 7 struct graph{ 8 int start,end,pointsize,tot; 9 int c[maxn<<1],to[maxn<<1],next[maxn<<1],head[maxn],dis[maxn],nowhead[maxn]; 10 void addedge(int a,int b,int l){ 11 c[++tot]=l;to[tot]=b;next[tot]=head[a];head[a]=tot; 12 c[++tot]=0;to[tot]=a;next[tot]=head[b];head[b]=tot; 13 } 14 int q[maxn],ql,qr; 15 bool BFS(){ 16 for (int i=1;i<=pointsize;++i) nowhead[i]=head[i],dis[i]=0; 17 ql=1; qr=0; q[++qr]=end; 18 while (ql<=qr){ 19 for (int k=q[ql++],p=head[k];p;p=next[p]) 20 if(c[p^1]&&!dis[to[p]]&&to[p]!=end) dis[q[++qr]=to[p]]=dis[k]+1; 21 } 22 return dis[start]; 23 } 24 int DFS(int k,int maxflow){ 25 if (k==end) return maxflow; 26 int flow=0,tflow; 27 for (int&p=nowhead[k];p&&maxflow;p=next[p]) 28 if(c[p]&&dis[to[p]]+1==dis[k]&&(tflow=DFS(to[p],min(maxflow,c[p])))) 29 c[p]-=tflow,c[p^1]+=tflow,maxflow-=tflow,flow+=tflow; 30 return flow; 31 } 32 int dinic(int a,int b){ 33 int flow=0; 34 start=a; end=b; 35 while (BFS()) flow+=DFS(a,inf); 36 return flow; 37 } 38 graph(){ 39 tot=1; 40 } 41 } G; 42 int main(){ 43 scanf("%d%d",&m,&n); 44 G.pointsize=m*n+2; 45 for (int i=1;i<=m;++i) 46 for (int j=1;j<=n;++j){ 47 scanf("%d",&a[i][j]); 48 ans+=a[i][j]; 49 } 50 for (int i=1;i<=m;++i) 51 for (int j=1;j<=n;++j) 52 if ((i+j)%2==0) { 53 if (j+1<=n) G.addedge((i-1)*n+j,(i-1)*n+j+1,inf); 54 if (i+1<=m) G.addedge((i-1)*n+j,i*n+j,inf); 55 if (j-1>=1) G.addedge((i-1)*n+j,(i-1)*n+j-1,inf); 56 if (i-1>=1) G.addedge((i-1)*n+j,(i-2)*n+j,inf); 57 } 58 for (int i=1;i<=m;++i) 59 for (int j=1;j<=n;++j) 60 if ((i+j)%2==0) G.addedge(m*n+1,(i-1)*n+j,a[i][j]); 61 else G.addedge((i-1)*n+j,m*n+2,a[i][j]); 62 printf("%d",ans-G.dinic(m*n+1,m*n+2)); 63 return 0; 64 }
声明:本博文为博主原创博文,未经允许请勿转载。