题意:
n
∗
m
n*m
n∗m的矩阵,每个点可以选择一个值
a
i
,
j
=
k
a_{i,j}=k
ai,j=k,然后你能获得
w
(
i
,
j
,
k
)
w(i,j,k)
w(i,j,k)的得分,但是相邻两点之间的差值有限制,让你求最大得分。
考虑最小割。
每个点 ( i , j ) (i,j) (i,j)弄出一条长为 R + 1 R+1 R+1的链,其中 k − > k + 1 k -> k+1 k−>k+1的流量为 w ( i , j , k ) w(i,j,k) w(i,j,k)。
考虑限制,只需要从这条链的 k k k到相邻一条链的 k − d k-d k−d连一无穷大的边,因为如果相邻的链选择的点 < k − d <k-d <k−d那么就会有流量剩余,因此就能进行限制了。
#include<bits/stdc++.h>
#define rep(i,x,y) for(int i=x;i<=y;i++)
#define dwn(i,x,y) for(int i=x;i>=y;i--)
#define ll long long
using namespace std;
template<typename T>inline void qr(T &x){
x=0;int f=0;char s=getchar();
while(!isdigit(s))f|=s=='-',s=getchar();
while(isdigit(s))x=x*10+s-48,s=getchar();
x=f?-x:x;
}
int cc=0,buf[31];
template<typename T>inline void qw(T x){
if(x<0)putchar('-'),x=-x;
do{buf[++cc]=int(x%10);x/=10;}while(x);
while(cc)putchar(buf[cc--]+'0');
}
const int N=5e5+10;
int n,m,k,d;
int h[N],st,ed,cur[N];
int tot=1,hd[N],ver[N*5],nxt[N*5],w[N*5];
int a[50][50][50],id[50][50][50],cnt;
void add(int x,int y,int z){
tot++;
ver[tot]=y;w[tot]=z;
nxt[tot]=hd[x];
hd[x]=tot;
}
void link(int x,int y,int z){
add(x,y,z),add(y,x,0);
}
bool bt_h(){
memset(h,0,sizeof(h));
h[st]=1;
queue<int>q;q.push(st);
while(q.size()){
int x=q.front();q.pop();
for(int i=hd[x];i;i=nxt[i]){
int y=ver[i];
if(w[i]&&!h[y]){
h[y]=h[x]+1;
q.push(y);
}
}
}
return h[ed];
}
int findflow(int x,int f){
if(x==ed)return f;
int res=f,tt;
for(int &i=cur[x];i;i=nxt[i]){
int y=ver[i];
if(w[i]&&h[y]==h[x]+1){
tt=findflow(y,min(res,w[i]));
w[i]-=tt,w[i^1]+=tt;
res-=tt;if(!res)break;
}
}
if(res==f)h[x]=0;
return f-res;
}
int dicnic(){
int ans=0;
while(bt_h()){
memcpy(cur,hd,sizeof(cur));
ans+=findflow(st,1e9);
}
return ans;
}
const int dx[4]={-1,1,0,0};
const int dy[4]={0,0,-1,1};
void solve(){
qr(n),qr(m),qr(k),qr(d);
rep(ki,1,k){
rep(i,1,n)rep(j,1,m)qr(a[ki][i][j]);
}
rep(ki,1,k+1){
rep(i,1,n)rep(j,1,m)id[ki][i][j]=++cnt;
}
st=cnt+1,ed=st+1;
rep(i,1,n)rep(j,1,m){
link(st,id[1][i][j],1e7);
link(id[k+1][i][j],ed,1e7);
}
rep(ki,1,k){
rep(i,1,n)rep(j,1,m){
link(id[ki][i][j],id[ki+1][i][j],a[ki][i][j]);
}
if(ki>d){
rep(i,1,n)rep(j,1,m){
rep(t,0,3){
int x=i+dx[t],y=j+dy[t];
if(1<=x&&x<=n&&1<=y&&y<=m){
link(id[ki][i][j],id[ki-d][x][y],1e7);
}
}
}
}
}
qw(dicnic());puts("");
}
int main(){
int tt;tt=1;
while(tt--)solve();
return 0;
}