NKOI 1944 方格取数问题

【线性规划与网络流24题 9】方格取数问题

Time Limit:10000MS  Memory Limit:65536K
Total Submit:20 Accepted:5 
Case Time Limit:1000MS

Description

在一个有m*n 个方格的棋盘中,每个方格中有一个正整数。现要从方格中取数,使任意2 个数所在方格没有公共边,且取出的数的总和最大。试设计一个满足要求的取数算法。 

编程任务: 
对于给定的方格棋盘,按照取数要求编程找出总和最大的数。

Input

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

Output

程序运行结束时,将取数的最大总和输出

Sample Input

3 3
1 2 3
3 2 3
2 3 1

Sample Output

11

Source

感谢 Wo_ai_WangYuan 放上数据


事实上是一个最大独立集的问题,将所有相邻的都看成是互相有边相连的,求出的最小割就是我们要舍弃的最小的点的权值之和,然后用权值总和减去最小割就是要的答案了

#include
#include
#include
using namespace std;
const int maxn=35,inf=1e9,maxm=1005;
inline void _read(int &x){
    char t=getchar();bool sign=true;
    while(t<'0'||t>'9')
    {if(t=='-')sign=false;t=getchar();}
    for(x=0;t>='0'&&t<='9';t=getchar())x=x*10+t-'0';
    if(!sign)x=-x;
}
int m,n,map1[maxn][maxn],map2[maxn][maxn],maxflow;
int op,ed,g[maxm][maxm],tot1,tot2,id[maxn][maxn];
int dis[maxm],vd[maxm];
int dfs(int u,int flow){      
    if(u==ed)return flow;      
    int v,temp,delta=0;      
    for(v=1;v<=ed;v++)      
        if(g[u][v]&&dis[u]==dis[v]+1){      
            temp=dfs(v,min(flow-delta,g[u][v]));      
            g[u][v]-=temp;      
            g[v][u]+=temp;      
            delta+=temp;      
            if(delta==flow||dis[op]>=ed)return delta;      
        }      
    if(dis[op]>=ed)return delta;      
    vd[dis[u]]--;      
    if(vd[dis[u]]==0)dis[op]=ed;      
    dis[u]++;      
    vd[dis[u]]++;      
    return delta;      
}
int main(){
	cin>>n>>m;
	int i,j,sum=0;
	for(i=1;i<=n;i++)
	    for(j=1;j<=m;j++){
	    	_read(map1[i][j]);
	    	sum+=map1[i][j];
	    }
	for(i=1;i<=n;i++){
		map2[i][1]=i&1;
		if(map2[i][1])id[i][1]=++tot1;
	}
	for(i=1;i<=n;i++)
	    for(j=2;j<=m;j++){
	    	map2[i][j]=1-map2[i][j-1];
	    	if(map2[i][j])id[i][j]=++tot1;
		}
	tot2=tot1;
	for(i=1;i<=n;i++)
	    for(j=1;j<=m;j++)
	        if(!map2[i][j])id[i][j]=++tot2;
	op=tot1+tot2+1,ed=op+1;
	for(i=1;i<=n;i++)
	    for(j=1;j<=m;j++){
	    	map2[i][j]?g[op][id[i][j]]=map1[i][j]:g[id[i][j]][ed]=map1[i][j];
	    	if(map2[i][j]){
	    		g[id[i][j]][id[i-1][j]]=g[id[i][j]][id[i+1][j]]=inf;
	    		g[id[i][j]][id[i][j-1]]=g[id[i][j]][id[i][j+1]]=inf;
			}
			else {
				g[id[i-1][j]][id[i][j]]=g[id[i+1][j]][id[i][j]]=inf;
	    		g[id[i][j-1]][id[i][j]]=g[id[i][j+1]][id[i][j]]=inf;
			}
		}
	while(dis[op]

你可能感兴趣的:(匈牙利算法及网络流)