• 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;
    }
  • 相关阅读:
    NSString
    xib和storyboard的使用方法
    drawRect画线和使用CGContext
    CGAffineTransform动画
    【概念】静态成员
    【c#】Application.Exit和Close有什么不同
    【c#】const和readonly关键字
    【概念】设计模式
    【概念】常见数据结构与算法
    【概念】索引器
  • 原文地址:https://www.cnblogs.com/shenben/p/6261731.html
Copyright © 2020-2023  润新知