题目描述
给出一个(N imes N)的矩阵,每一格有一个非负整数(a[i][j])每次走过时可以取出这个数,走过多次只算一次,求走(k)次取得的最大代价
问题求解
如果(k=1)的话,显然可以用(DP)来解决,但是(k>1)时前一种的走法对下一次产生了影响,所以考虑用网络流来做
把每个点看成是一个入点和一个出点,每个格子,我们可以从入点到出点建一条流量为(1),费用为(a[i][j])的边,和(k-1)条流量为(k-1),费用为(0)的边,表示一个数的代价只算一次,为了保证图的连通性,讲(i,j)向边上建流量为(k),费用为(0)的边
最后答案就是从((1,1))的入点到((n,n))的出点的最大流
代码实现
#include<bits/stdc++.h>
using namespace std;
const int maxn=5010,maxe=maxn*8,INF=0x3f3f3f3f;
int N,K,mp[55][55],T;
int lnk[maxn],nxt[maxe],son[maxe],w[maxe],cost[maxe],cnt=1,vis[maxn],cur[maxn],Q[maxn],dis[maxn];
int maxflow,mincost,st,ed;
inline int read(){
int ret=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
while(ch<='9'&&ch>='0')ret=ret*10+ch-'0',ch=getchar();
return ret*f;
}
void add_e(int x,int y,int z,int c){son[++cnt]=y;nxt[cnt]=lnk[x];lnk[x]=cnt;w[cnt]=z;cost[cnt]=c;}
void add_edge(int x,int y,int z,int c){add_e(x,y,z,c);add_e(y,x,0,-c);}
inline int calc(int x,int y){return N*(x-1)+y;}
int spfa(){
int hed=0,til=1;Q[til]=st;
memset(dis,INF,sizeof dis);dis[st]=0;
while(hed!=til){
hed=(hed+1)%maxn;vis[Q[hed]]=0;
for(int j=lnk[Q[hed]];j;j=nxt[j]){
if(w[j]>0&&dis[son[j]]>dis[Q[hed]]+cost[j]){
dis[son[j]]=dis[Q[hed]]+cost[j];
if(!vis[son[j]]){
vis[son[j]]=1;Q[til=(til+1)%maxn]=son[j];
}
}
}
}
return dis[ed]!=INF;
}
int DFS(int x,int delta){
if(x==ed)return delta;
int flow=0;vis[x]=1;
for(int j=cur[x];j;j=nxt[j]){
if(!vis[son[j]]&&w[j]&&dis[son[j]]==dis[x]+cost[j]){
cur[x]=j;
int t=DFS(son[j],min(delta-flow,w[j]));
flow+=t;w[j]-=t;w[j^1]+=t;mincost+=t*cost[j];
if(flow==delta)break;
}
}
vis[x]=0;
return flow;
}
void Dinic(){
while(spfa()){
memcpy(cur,lnk,sizeof cur);
int tmp=DFS(st,INF);
if(!tmp)break;
maxflow+=tmp;
}
}
int main(){
N=read();K=read();T=N*N;
for(int i=1;i<=N;i++)for(int j=1;j<=N;j++)mp[i][j]=read();
st=1;ed=2*T;
for(int i=1;i<=N;i++)
for(int j=1;j<=N;j++){
add_edge(calc(i,j),calc(i,j)+T,1,-mp[i][j]);
add_edge(calc(i,j),calc(i,j)+T,K-1,0);
if(i<N)add_edge(calc(i,j)+T,calc(i+1,j),K,0);
if(j<N)add_edge(calc(i,j)+T,calc(i,j+1),K,0);
}
Dinic();
printf("%d
",-mincost);
return 0;
}