codevs1227 方格取数2

题目描述 Description

给出一个n*n的矩阵,每一格有一个非负整数Aij,(Aij <= 1000)现在从(1,1)出发,可以往右或者往下走,最后到达(n,n),每达到一格,把该格子的数取出来,该格子的数就变成0,这样一共走K次,现在要求K次所达到的方格的数的和最大

输入描述 Input Description

第一行两个数n,k(1<=n<=50, 0<=k<=10)

接下来n行,每行n个数,分别表示矩阵的每个格子的数

输出描述 Output Description

一个数,为最大和

样例输入 Sample Input

3 1

1 2 3

0 2 1

1 4 2

样例输出 Sample Output

11

数据范围及提示 Data Size & Hint

1<=n<=50, 0<=k<=10

拆点 x与x'之间连两条边,一条费用为格子里的数值,最大流量为1,另一条费用为0,最大流量INF

费用流

//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=2*50*50+10,maxm=4*maxn+maxn,INF=0x3f3f3f3f;
int n,k,tu[maxn],S,T;

int aa;char cc;
int read() {
	aa=0;cc=getchar();
	while(cc<'0'||cc>'9') cc=getchar();
	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
	return aa;
}

struct Node{
	int x,y,cap,flow,w;
	Node(){}
	Node(int x,int y,int cap,int w) :x(x),y(y),cap(cap),w(w){}
}node[2*maxm];

int fir[maxn],nxt[2*maxm],e=1;
void add(int x,int y,int z,int w) {
	node[++e]=Node(x,y,z,w); nxt[e]=fir[x];fir[x]=e;
	node[++e]=Node(y,x,0,-w); nxt[e]=fir[y];fir[y]=e;
}

int zz[maxn],from[maxn],dis[maxn];bool vis[maxn];
bool spfa() {
	int s=1,t=0,x,y,z;
	memset(dis,-1,sizeof(dis));
	memset(zz,0,sizeof(zz));
	zz[++t]=S;vis[S]=1;dis[S]=0;
	while(s<=t) {
		x=zz[s%maxn];
		for(y=fir[x];y;y=nxt[y]) {
			z=node[y].y;
			if(dis[z]>=dis[x]+node[y].w||node[y].flow>=node[y].cap) continue;
			if(!vis[z]) {
				t++; zz[t%maxn]=z;
				vis[z]=1;
			}
			from[z]=y;
			dis[z]=dis[x]+node[y].w;
		}
		vis[x]=0;s++;
	}
	return dis[T]!=-1;
}

int MCMF() {
	int rs=0,now;
	while(spfa()) {
		now=INF;
		for(int i=T;i!=S;i=node[from[i]].x) now=min(now,node[from[i]].cap-node[from[i]].flow);
		for(int i=T;i!=S;i=node[from[i]].x) {
			node[from[i]].flow+=now;
			node[from[i]^1].flow-=now;
			rs+=now*node[from[i]].w;
		}
	}
	return rs;
}

int main() {
	n=read();k=read();int x;S=2*n*n+1;T=S+1;
	for(int i=1;i<=n*n;++i) tu[i]=read();
	for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) {
		x=n*(i-1)+j;
		add(x+n*n,x,1,tu[x]);add(x+n*n,x,k,0);
		if(i!=n) add(x,x+n+n*n,k,0);
		if(j!=n) add(x,x+1+n*n,k,0);
	}
	add(S,1+n*n,k,0); add(n*n,T,k,0);
	printf("%d",MCMF());
	return 0;
}

  

弱者就是会被欺负呀
原文地址:https://www.cnblogs.com/Serene-shixinyi/p/7445459.html