«问题描述:
在一个有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("\n"); 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 }
时间: 2024-11-16 05:24:38