【bzoj3144】[Hnoi2013]切糕

来源:互联网 发布:软件实施做什么的 编辑:程序博客网 时间:2024/04/26 04:38

每个点(x,y,z)(x,y,z+1)连一条容量为其代价的边
S(x,y,1)连一条容量为inf的边
(x,y,h+1)T连一条容量为inf的边
对于相邻的(x,y),(x,y),连边(x,y,P)>(x,y,PD),容量为inf,保证相邻两纵列高度差小于D

#include <bits/stdc++.h>#define gc getchar()#define ll long long#define mid (l+r>>1)#define N 80009#define inf 0x3f3f3f3fusing namespace std;const int fx[4]={0,1,0,-1};const int fy[4]={1,0,-1,0};int n,m,h,D;int number=1,pos,cur[N],dis[N];bool vis[N];vector<int> G[N];struct edge{    int from,to,flow,cap;    int rest()    {        return cap-flow;    }    void add(int x,int y,int z)    {        from=x,to=y,cap=z,flow=0;    }}e[3000009];void add(int x,int y,int z,int zz=0){    e[++number].add(x,y,z);    G[x].push_back(number);    e[++number].add(y,x,zz);    G[y].push_back(number);}#define E e[G[x][i]]bool bfs(int s,int t){    memset(vis,0,sizeof(vis));    queue<int> Q;    Q.push(s);    dis[s]=0;    vis[s]=1;    while (!Q.empty())    {        int x=Q.front();        Q.pop();        for (int i=0;i<(int)G[x].size();i++)            if (!vis[E.to]&&E.rest()>0)            {                vis[E.to]=1;                dis[E.to]=dis[x]+1;                Q.push(E.to);            }    }    return vis[t];}int dfs(int x,int a,int t){    if (x==t||a==0) return a;    int flow=0,f;    for (int &i=cur[x];i<(int)G[x].size();i++)        if (dis[x]+1==dis[E.to]&&(f=dfs(E.to,min(a,E.rest()),t))>0)        {            E.flow+=f;            e[G[x][i]^1].flow-=f;            flow+=f;            a-=f;            if (!a) break;        }    return flow;}int Maxflow(int s,int t){    int flow=0;    while (bfs(s,t))    {        memset(cur,0,sizeof(cur));        flow+=dfs(s,inf,t);    }    return flow;}#undef Eint read(){    int x=1;    char ch;    while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;    int s=ch-'0';    while (ch=gc,ch>='0'&&ch<='9') s=s*10+ch-'0';    return s*x;}int get(int x,int y,int z){    return (x-1)*n*m+(y-1)*m+z;}int main(){    n=read(),m=read(),h=read();    D=read();    for (int k=1;k<=h;k++)        for (int i=1;i<=n;i++)            for (int j=1;j<=m;j++)            {                int x=read();                add(get(k,i,j),get(k+1,i,j),x);                if (k==1)                {                    add(0,get(1,i,j),inf);                    add(get(h+1,i,j),(h+1)*n*m+1,inf);                }                if (k>D)                {                    for (int p=0;p<4;p++)                    {                        int xx=i+fx[p],yy=j+fy[p];                        if (xx>=1&&xx<=n&&yy>=1&&yy<=m)                            add(get(k,i,j),get(k-D,xx,yy),inf);                    }                }            }    printf("%d\n",Maxflow(0,(h+1)*n*m+1));    return 0;}
原创粉丝点击