P3227 [HNOI2013] 切糕

题意:
n ∗ m n*m nm的矩阵,每个点可以选择一个值 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 kd连一无穷大的边,因为如果相邻的链选择的点 < k − d <k-d <kd那么就会有流量剩余,因此就能进行限制了。

#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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值