• bzoj 3144: [Hnoi2013]切糕


    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

    solution

    用a[n][m][h]记录不和谐值

    建模:

    1.将 S 与最底层的点连 一条a[i][j][1] 的边

    2.将每一个轴上的每一个点与其上面的点连一条 容量为上一个点不和谐值的边

    3.将最上层的点 与 T点连一条 INF 的边

    4.最重要的:为了限制  |f(x,y)-f(x1,y1)|<=D 这个条件,我们将每一个点向 与它相邻的 并且比它低D的 点连一条INF的边(当然 没有就不用连了)

    证明其正确性:

    当两个截点d>D时,还会有增光路

    而如果在右边轴上面>D的地方截的话,还会有增广路

    而如果在<=D的地方截的话,>D截的点又没有了必要

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<queue>
      4 #include<iostream>
      5 #define mem(a,b) memset(a,b,sizeof(a))
      6 #define ll long long
      7 #define dd double
      8 using namespace std;
      9 const int INF=(1<<31)-1;
     10 const int N=2006;
     11 inline int minn(int a,int b){return a<b?a:b;}
     12 struct son
     13 {
     14     int u,v,next;
     15     int w;
     16 };
     17 son a1[3000006];
     18 int first[3000006],e;
     19 void addbian(int u,int v,int w)
     20 {
     21     a1[e].v=v;
     22     a1[e].w=w;
     23     a1[e].u=u;
     24     a1[e].next=first[u];
     25     first[u]=e++;
     26 }
     27 void Link(int u,int v,int w)
     28 {
     29     addbian(u,v,w);
     30     addbian(v,u,0);
     31 }
     32 void Match(int u,int v,int w)
     33 {
     34     addbian(u,v,w);
     35     addbian(v,u,w);
     36 }
     37 
     38 int n,m,h,D;
     39 int S,T,ha[46][46][46];
     40 int a[46][46][46];
     41 
     42 int dui[1000001],he,en;
     43 inline void clear(){he=1;en=0;}
     44 inline void push(int x){dui[++en]=x;}
     45 inline int top(){return dui[he];}
     46 inline void pop(){++he;}
     47 inline bool empty(){return en>=he?0:1;}
     48 
     49 int dep[64666];
     50 int bfs()
     51 {
     52     mem(dep,0);clear();
     53     dep[S]=1;push(S);
     54     while(!empty())
     55     {
     56         int now=top();pop();
     57         for(int i=first[now];i!=-1;i=a1[i].next)
     58         {
     59             int temp=a1[i].v;
     60             if(!a1[i].w||dep[temp])continue;
     61             dep[temp]=dep[now]+1;
     62             push(temp);
     63             if(temp==T)return 1;
     64         }
     65     }
     66     return 0;
     67 }
     68 
     69 int dfs(int x,int val)
     70 {
     71     if(x==T)return val;
     72     int val2=val,k;
     73     for(int i=first[x];i!=-1;i=a1[i].next)
     74     {
     75         int temp=a1[i].v;
     76         if(!a1[i].w||dep[temp]!=dep[x]+1||!val2)continue;
     77         k=dfs(temp,minn(val2,a1[i].w));
     78         if(!k){dep[temp]=0;continue;}
     79         a1[i].w-=k;a1[i^1].w+=k;val2-=k;
     80     }
     81     return val-val2;
     82 }
     83 
     84 int Dinic()
     85 {
     86     int ans=0;
     87     while(bfs())
     88       ans+=dfs(S,INF);
     89     return ans;
     90 }
     91 
     92 int main(){
     93     mem(first,-1);
     94     scanf("%d%d%d",&n,&m,&h);
     95     scanf("%d",&D);
     96     for(int k=1;k<=h;++k)
     97       for(int i=1;i<=n;++i)
     98         for(int j=1;j<=m;++j)
     99         {scanf("%d",&a[i][j][k]);ha[i][j][k]=(k-1)*n*m+(i-1)*m+j;}
    100     
    101     S=0;T=n*m*h+1;
    102     
    103     for(int i=1;i<=n;++i)
    104       for(int j=1;j<=m;++j)
    105         Link(S,ha[i][j][1],a[i][j][1]);
    106     
    107     for(int k=1;k<h;++k)
    108       for(int i=1;i<=n;++i)
    109         for(int j=1;j<=m;++j)
    110           Link(ha[i][j][k],ha[i][j][k+1],a[i][j][k+1]);
    111     
    112     for(int i=1;i<=n;++i)
    113       for(int j=1;j<=m;++j)
    114         Link(ha[i][j][h],T,INF);
    115     
    116     for(int k=D;k<=h;++k)
    117       for(int i=1;i<=n;++i)
    118         for(int j=1;j<=m;++j)
    119         {
    120                 if(i>1)Link(ha[i][j][k],ha[i-1][j][k-D],INF);
    121                 if(i<n)Link(ha[i][j][k],ha[i+1][j][k-D],INF);
    122                 if(j>1)Link(ha[i][j][k],ha[i][j-1][k-D],INF);
    123                 if(j<m)Link(ha[i][j][k],ha[i][j+1][k-D],INF);
    124             }
    125     
    126     printf("%d",Dinic());
    127     //while(1);
    128     return 0;
    129 }
    code
  • 相关阅读:
    精简菜单和完整菜单之间进行切换
    QBC运算符含义
    STL源代码剖析——STL算法stl_algo.h
    TI_DSP_corePac_带宽管理
    scrapy-redis源代码分析
    SVG 贝塞尔曲线控制【方便设置】:贝塞尔曲线
    Zoj 2100 Seeding
    快慢指针和链表原地反转
    Gradle 编译多个project(包括多Library库project依赖)指导
    供应商地点信息更新
  • 原文地址:https://www.cnblogs.com/A-LEAF/p/7261274.html
Copyright © 2020-2023  润新知