首页 > 代码库 > 3144: [Hnoi2013]切糕

3144: [Hnoi2013]切糕

3144: [Hnoi2013]切糕

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 1526  Solved: 827
[Submit][Status][Discuss]

Description

技术分享

Input

第一行是三个正整数P,Q,R,表示切糕的长P、 宽Q、高R。第二行有一个非负整数D,表示光滑性要求。接下来是R个P行Q列的矩阵,第z个 矩阵的第x行第y列是v(x,y,z) (1≤x≤P, 1≤y≤Q, 1≤z≤R)。 
100%的数据满足P,Q,R≤40,0≤D≤R,且给出的所有的不和谐值不超过1000。

Output

仅包含一个整数,表示在合法基础上最小的总不和谐值。

Sample Input

2 2 2
1
6 1
6 1
2 6
2 6

Sample Output

6

HINT

 

最佳切面的f为f(1,1)=f(2,1)=2,f(1,2)=f(2,2)=1

 

Source

 

经典最小割模型

题面简化为,一个矩阵,每个格子分配一个数,不同的数字,代价不同,要求相邻格子数字差小等于d

求最小代价

每个格子拆出40个点

连同S与T用40种代价串起来

即 p(x,y,z)->p(x,y,z+1)边权f(x,y,z+1)

然后 p(x,y,z)->p(x’,y’,z-d)边权inf (x,y)与(x’,y’)相邻

把边画出来正确性很显然

技术分享

 

#include<cstdio>#include<cstring>#include<queue>using namespace std;int read(){    register int x=0;bool f=1;    register char ch=getchar();    while(ch<0||ch>9){if(ch==-)f=0;ch=getchar();}    while(ch>=0&&ch<=9){x=(x<<3)+(x<<1)+ch-0;ch=getchar();}    return f?x:-x;}const int N=50;const int M=N*N*N;const int inf=2e9;int n,m,S,T,head[M],dis[M],q[M*10];bool vis[M];int P,Q,R,D,mp[N][N][N],id[N][N][N],cnt;struct node{    int v,next,cap;}e[M*10];int tot=1;void add(int x,int y,int z){    e[++tot].v=y;e[tot].cap=z;e[tot].next=head[x];head[x]=tot;    e[++tot].v=x;e[tot].cap=0;e[tot].next=head[y];head[y]=tot;}bool bfs(){    for(int i=S;i<=T;i++) dis[i]=inf;    int h=0,t=1;q[t]=S;dis[S]=0;    while(h!=t){        int x=q[++h];        for(int i=head[x];i;i=e[i].next){            int v=e[i].v;            if(e[i].cap&&dis[v]>dis[x]+1){                dis[v]=dis[x]+1;                if(v==T) return 1;                q[++t]=v;            }        }    }    return dis[T]<inf;}int dfs(int x,int f){    if(x==T) return f;    int used=0,t;    for(int i=head[x];i;i=e[i].next){        int v=e[i].v;        if(e[i].cap&&dis[v]==dis[x]+1){            t=dfs(v,min(f,e[i].cap));            e[i].cap-=t;e[i^1].cap+=t;            used+=t;f-=t;            if(!f) return used;        }    }    if(!used) dis[x]=0;    return used;}int dinic(){    int res=0;    while(bfs()) res+=dfs(S,inf);    return res;}int main(){    scanf("%d%d%d%d",&P,&Q,&R,&D);    for(int i=1;i<=R;i++){        for(int j=1;j<=P;j++){            for(int k=1;k<=Q;k++){                scanf("%d",&mp[i][j][k]);                id[i][j][k]=++cnt;            }        }    }    S=0,T=cnt+1;    for(int i=1;i<=R;i++){        for(int j=1;j<=P;j++){            for(int k=1;k<=Q;k++){                if(i==1)                    add(S,id[i][j][k],mp[i][j][k]);                else                    add(id[i-1][j][k],id[i][j][k],mp[i][j][k]);                if(i==R)                    add(id[i][j][k],T,inf);                if(i>D){                    if(j!=1) add(id[i][j][k],id[i-D][j-1][k],inf);                    if(j!=P) add(id[i][j][k],id[i-D][j+1][k],inf);                    if(k!=1) add(id[i][j][k],id[i-D][j][k-1],inf);                    if(k!=Q) add(id[i][j][k],id[i-D][j][k+1],inf);                }            }        }    }    printf("%d",dinic());    return 0;}

 

3144: [Hnoi2013]切糕