方格取数问题
Description
在一个有
mn
个方格的棋盘中,每个方格中有一个正整数。
现要从方格中取数,使任意
2
个数所在方格没有公共边,且取出的数的总和最大。
试设计一个满足要求的取数算法。
Input
文件第
接下来的
Output
程序运行结束时,将取数的最大总和输出到文件中。
Sample Input
3 3
1 2 3
3 2 3
2 3 1
Sample Output
11
HINT
Solution
第一次做棋盘形的网络流,有点小激动。
一看就觉得这个题目有点水。
把横坐标和纵坐标相加为偶数的格子往四周连容量为无限大的边。
将源点与(横坐标和纵坐标相加为偶数的格子)连一条容量为其格子上的数字的边。
将汇点与(横坐标和纵坐标相加为奇数的格子)连一条容量为七个字上的数字的边。
求最小切割,然后用所有的数字之和减去最小切割即可。
Code
- #include <iostream>
- #include <cstdio>
- #include <cstring>
- #include <queue>
- #define Min(x,y) ((x)<(y)?(x):(y))
- #define PLA(x,y) ((((x)-1)*n)+(y))
- #define INF 0x3f3f3f3f
- #define ss 9999
- #define tt 10000
- using namespace std;
- int m,n,cnt,sum;
- int map[30][30];
- int head[101000],nxt[1000010];
- int data[1000010],flow[1000010];
- int dis[101000];
- queue<int>q;
- void add(int x,int y,int z){
- nxt[cnt]=head[x];data[cnt]=y;flow[cnt]=z;head[x]=cnt++;
- nxt[cnt]=head[y];data[cnt]=x;flow[cnt]=0;head[y]=cnt++;
- }
- bool BFS(){
- memset(dis,-1,sizeof dis);
- dis[ss]=0;
- q.push(ss);
- while(!q.empty()){
- int now=q.front();
- q.pop();
- for(int i=head[now];i!=-1;i=nxt[i]){
- if(flow[i]&&dis[data[i]]==-1){
- q.push(data[i]);
- dis[data[i]]=dis[now]+1;
- }
- }
- }
- return dis[tt]>0;
- }
- int dfs(int now,int low){
- if(now==tt)return low;
- int Low;
- for(int i=head[now];i!=-1;i=nxt[i]){
- if(flow[i]&&dis[data[i]]==dis[now]+1){
- if(Low=dfs(data[i],Min(low,flow[i]))){
- flow[i]-=Low;
- flow[i^1]+=Low;
- return Low;
- }
- }
- }
- return 0;
- }
- int main(){
- freopen(”grid.in”,“r”,stdin);
- freopen(”grid.out”,“w”,stdout);
- memset(head,-1,sizeof head);
- scanf(”%d%d”,&m,&n);
- for(int i=1;i<=m;i++)
- for(int j=1;j<=n;j++)
- scanf(”%d”,&map[i][j]);
- for(int i=1;i<=m;i++)
- for(int j=1;j<=n;j++){
- if(!((i+j)&1)){
- add(ss,PLA(i,j),map[i][j]);
- if(i+1<=m)add(PLA(i,j),PLA(i+1,j),INF);
- if(j+1<=n)add(PLA(i,j),PLA(i,j+1),INF);
- if(i-1>=1)add(PLA(i,j),PLA(i-1,j),INF);
- if(j-1>=1)add(PLA(i,j),PLA(i,j-1),INF);
- }
- else
- add(PLA(i,j),tt,map[i][j]);
- sum+=(map[i][j]);
- }
- int flag,weight=0;
- while(BFS())
- while(flag=dfs(ss,INF))weight+=flag;
- printf(”%d\n”,sum-weight);
- return 0;
- }