比赛描述
在一个有m*n 个方格的棋盘中,每个方格中有一个正整数。现要从方格中取数,使任意2 个数所在方格没有公共边,且取出的数的总和最大。试设计一个满足要求的取数算法。
对于给定的方格棋盘,按照取数要求编程找出总和最大的数。
输入
第1行有2个正整数m和n,分别表示棋盘的行数和列数。接下来的m行,每行有n个正整数,表示棋盘方格中的数
输出
程序运行结束时,将取数的最大总和输出。
样例输入
3 3
1 2 3
3 2 3
2 3 1
样例输出
11
提示
题目来源
算法设计与实验题解
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int VM=2520; const int EM=5010; const int INF=0x3f3f3f3f; struct Edge{ int u,v,nxt; int flow; }edge[EM<<1]; int n,m,cnt,head[VM]; int src,des,dep[VM]; void addedge(int cu,int cv,int cf){ edge[cnt].u=cu; edge[cnt].v=cv; edge[cnt].flow=cf; edge[cnt].nxt=head[cu]; head[cu]=cnt++; edge[cnt].u=cv; edge[cnt].v=cu; edge[cnt].flow=0; edge[cnt].nxt=head[cv]; head[cv]=cnt++; } int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}}; int legal(int i,int j,int k){ int x=i+dir[k][0]; int y=j+dir[k][1]; return x>=1 && x<=n && y>=1 && y<=m; } int BFS(){ // 重新 建 图 (按 层数 建图) queue<int> q; while(!q.empty()) q.pop(); memset(dep,-1,sizeof(dep)); dep[src]=0; q.push(src); while(!q.empty()){ int u=q.front(); q.pop(); for(int i=head[u];i!=-1;i=edge[i].nxt){ int v=edge[i].v; if(edge[i].flow>0 && dep[v]==-1){ // 如果 可以 可以到达 但 还没有 访问 dep[v]=dep[u]+1; q.push(v); } } } return dep[des]!=-1; } /* int DFS(int u,int minx){ // 查找 路径上的 最小 的 流量 if(u==des) return minx; int tmp; for(int i=head[u];i!=-1;i=edge[i].nxt){ int v=edge[i].v; if(edge[i].flow>0 && dep[v]==dep[u]+1 && (tmp=DFS(v,min(minx,edge[i].flow)))){ edge[i].flow-=tmp; edge[i^1].flow+=tmp; return tmp; } //printf("!!!!!!\n"); } return 0; } */ int DFS(int u,int minx){ int ans=0; if(u==des) return minx; for(int i=head[u];i!=-1 && ans<minx;i=edge[i].nxt){ int v=edge[i].v; if(edge[i].flow>0 && dep[v]==dep[u]+1){ int tmp=min(edge[i].flow,minx-ans); tmp=DFS(v,tmp); ans+=tmp; edge[i].flow-=tmp; edge[i^1].flow+=tmp; } } if(!ans) dep[u]=-2; return ans; } int Dinic(){ int ans=0,tmp; while(BFS()){ while(1){ tmp=DFS(src,INF); if(tmp==0) break; ans+=tmp; } } return ans; } int main(){ //freopen("input.txt","r",stdin); while(~scanf("%d%d",&n,&m)){ cnt=0; memset(head,-1,sizeof(head)); int x,sum=0; src=0; des=n*m+1; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ scanf("%d",&x); sum+=x; if((i+j)%2==0){ addedge(src,(i-1)*m+j,x); for(int k=0;k<4;k++){ if(legal(i,j,k)) addedge((i-1)*m+j,(i+dir[k][0]-1)*m+(j+dir[k][1]),INF); } }else{ addedge((i-1)*m+j,des,x); for(int k=0;k<4;k++){ if(legal(i,j,k)) addedge((i+dir[k][0]-1)*m+(j+dir[k][1]),(i-1)*m+j,INF); } } } int maxflow=Dinic(); printf("%d\n",sum-maxflow); } return 0; } /*8MS #include<iostream> #include<cstring> #include<cstdio> #define INF 0x7fffffff using namespace std; int n,m,cnt=1,head[1001],h[1001],ans; int xx[4]={0,0,1,-1},yy[4]={1,-1,0,0}; int mp[31][31],mark[31][31]; struct data{int to,next,v;}e[10001]; bool jud(int x,int y){if(x<1||y<1||x>n||y>m)return 0;return 1;} void ins(int u,int v,int w) {cnt++;e[cnt].to=v;e[cnt].v=w;e[cnt].next=head[u];head[u]=cnt;} void insert(int u,int v,int w) {ins(u,v,w);ins(v,u,0);} void INS(){ for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if((i+j)%2==0) { insert(0,mark[i][j],mp[i][j]); for(int k=0;k<4;k++) { if(jud(i+xx[k],j+yy[k])){insert(mark[i][j],mark[i+xx[k]][j+yy[k]],INF);} } } else insert(mark[i][j],n*m+1,mp[i][j]); } bool bfs() { int q[40002],t=0,w=1,i,now; memset(h,-1,sizeof(h)); q[0]=h[0]=0; while(t<w) { now=q[t];t++; i=head[now]; while(i) { if(e[i].v&&h[e[i].to]<0){h[e[i].to]=h[now]+1;q[w++]=e[i].to;} i=e[i].next; } } if(h[n*m+1]==-1)return 0; return 1; } int dfs(int x,int f) { if(x==n*m+1)return f; int i=head[x]; int w,used=0; while(i) { if(e[i].v&&h[e[i].to]==h[x]+1) { w=f-used; w=dfs(e[i].to,min(w,e[i].v)); e[i].v-=w; e[i^1].v+=w; used+=w; if(used==f)return f; } i=e[i].next; } if(!used)h[x]=-1; return used; } void dinic(){while(bfs())ans-=dfs(0,INF);} int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { scanf("%d",&mp[i][j]); ans+=mp[i][j]; } int b=0,w=(n*m+1)/2; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if((i+j)%2==0){b++;mark[i][j]=b;} else{w++;mark[i][j]=w;} INS(); dinic(); printf("%d",ans); return 0; } */ /*Time Limit Exceed at Test 3 #include<stdio.h> #define N 200 int m,n,max_val,current; int a[N][N]; bool visited[N][N]; void handle(int i, int j){ if( !visited[i][j] && ( (0==j) || !visited[i][j-1]) && ( (0==i) || !visited[i-1][j]) && ( (m-1==j) || !visited[i][j+1]) && ( (n-1==i) || !visited[i+1][j]) ){ current += a[i][j]; visited[i][j] = 1; if(n-1==j){ if(m-1==i){ if(max_val<current){ max_val = current; } }else{ handle(i+1,0); } }else{ handle(i,j+1); } current -= a[i][j]; visited[i][j]=0; } if(n-1==j){ if(i<m-1){ handle(i+1,0); }else{ if(max_val<current){ max_val = current; } } }else{ handle(i,j+1); } } int main(){ int i,j; scanf("%d%d",&m,&n); for(i=0; i<m; i++){ for(j=0; j<n; j++){ scanf("%d",&a[i][j]); } } handle(0,0); printf("%d\n",max_val); } */