bzoj千题计划142:bzoj3144: [Hnoi2013]切糕

http://www.lydsy.com/JudgeOnline/problem.php?id=3144

 

如果D=2 ,两个点,高度为4,建图如下

 

 

 

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>

using namespace std;
 
#define N 64005
#define M 323205
const int inf=2e9;
 
int n;

int P,Q,R,D;
int cost[41][41][41];
 
int tot=1;
int front[N],nxt[M<<1],to[M<<1],val[M<<1],from[M<<1];
int lev[N],num[N];
int path[N];
int cur[N];
 
int src,decc;

int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};

void read(int &x)
{
    x=0; char c=getchar();
    while(!isdigit(c))  c=getchar(); 
    while(isdigit(c)) { x=x*10+c-'0'; c=getchar();  }
}

void add(int u,int v,int w)
{
    to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; from[tot]=u; val[tot]=w;
    to[++tot]=u; nxt[tot]=front[v]; front[v]=tot; from[tot]=v; val[tot]=0;
   // cout<<u<<' '<<v<<' '<<w<<'\n';
}

bool bfs()
{
    queue<int>q;
    for(int i=src;i<=decc;++i) lev[i]=decc;
    q.push(decc);
    lev[decc]=0;
    int now,t;
    while(!q.empty())
    {
        now=q.front();
        q.pop();
        for(int i=front[now];i;i=nxt[i])
        {
            t=to[i];
            if(lev[t]==decc && val[i^1]) 
            {
                lev[t]=lev[now]+1;
                q.push(t);
            }
        }
    }
    return lev[src]!=decc;
}
 
int augment()
{
    int now=decc,flow=inf;
    int i;
    while(now!=src)
    {
        i=path[now];
        flow=min(flow,val[i]);
        now=from[i];
    }
    now=decc;
    while(now!=src)
    {
        i=path[now];
        val[i]-=flow;
        val[i^1]+=flow;
        now=from[i];
    }
    return flow;
}
 
int isap()
{
    int flow=0;
    if(!bfs()) return 0;
    memset(num,0,sizeof(num));
    for(int i=src;i<=decc;++i) num[lev[i]]++,cur[i]=front[i];
    int now=src,t;
    while(lev[src]<=decc)
    {
        if(now==decc)
        {
            flow+=augment();
            now=src;
        }
        bool advanced=false;
        for(int i=cur[now];i;i=nxt[i])
        {
            t=to[i];
            if(lev[t]==lev[now]-1 && val[i])
            {
                advanced=true;
                path[t]=i;
                cur[now]=i;
                now=t;
                break;
            }
        }
        if(!advanced)
        {
            int mi=decc;
            for(int i=front[now];i;i=nxt[i])
                if(val[i]) mi=min(mi,lev[to[i]]);
            if(!--num[lev[now]]) break;
            num[lev[now]=mi+1]++;
            cur[now]=front[now];
            if(now!=src) now=from[path[now]];
        }
    }
       return flow;
}

int turn(int i,int j,int k)
{
    return ((i-1)*Q+j-1)*(R+1)+k;
}

void build()
{
    int nx,ny;
    for(int i=1;i<=P;++i)
        for(int j=1;j<=Q;++j)
            for(int k=1;k<=R;++k)
            {
                add(turn(i,j,k),turn(i,j,k+1),cost[i][j][k]);
                if(k>D)
                {
                    for(int d=0;d<4;++d)
                    {
                        nx=i+dx[d]; ny=j+dy[d];
                        if(nx>=1 && nx<=P && ny>=1 && ny<=Q) add(turn(i,j,k),turn(nx,ny,k-D),inf);
                    }
                }
            }
    decc=P*Q*(R+1)+1;
    for(int i=1;i<=P;++i)
        for(int j=1;j<=Q;++j)
        {
            add(src,turn(i,j,1),inf);
            add(turn(i,j,R+1),decc,inf);
        }
}

int main()
{
    freopen("nutcake.in","r",stdin);
    freopen("nutcake.out","w",stdout);
    read(P); read(Q); read(R);
    read(D);
    for(int i=1;i<=R;++i)
        for(int j=1;j<=P;++j)
            for(int k=1;k<=Q;++k)
            {
                read(cost[j][k][i]);
            //    cout<<j<<' '<<k<<' '<<i<<' '<<cost[j][k][i]<<'\n';
            }        
    build();
    cout<<isap();
}

 

2018.3.20 考试代码

#include<queue>
#include<cstdio>
#include<iostream>

using namespace std;

const int inf=2e9;

#define M 400000
#define N 70000

int P,Q,R,D;
int a[41][41][41];

int front[N],nxt[M<<1],to[M<<1],cap[M<<1],tot=1;

int src,decc;
int lev[N],cur[N];
queue<int>q;

void read(int &x)
{
    x=0; char c=getchar();
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
}

void init()
{
    read(P); read(Q); read(R);
    read(D);
    for(int i=1;i<=R;++i)
        for(int j=1;j<=P;++j)
            for(int k=1;k<=Q;++k)
                read(a[i][j][k]);
}

int turn(int i,int j,int k)
{
    return ((i-1)*Q+j-1)*(R+1)+k;
}

void add(int u,int v,int val)
{
    to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; cap[tot]=val;
    to[++tot]=u; nxt[tot]=front[v]; front[v]=tot; cap[tot]=0;
}

void build()
{
    decc=(R+1)*P*Q+1;
    for(int i=1;i<=P;++i)
        for(int j=1;j<=Q;++j)
        {
            add(src,turn(i,j,1),inf);
            for(int k=1;k<=R;++k)
                add(turn(i,j,k),turn(i,j,k+1),a[k][i][j]);
            add(turn(i,j,R+1),decc,inf);
        }
    for(int i=1;i<=P;++i)
        for(int j=1;j<=Q;++j)
            for(int k=D+2;k<=R+1;++k)
            {
                if(i>1) add(turn(i,j,k),turn(i-1,j,k-D),inf);
                if(i<P) add(turn(i,j,k),turn(i+1,j,k-D),inf);
                if(j>1) add(turn(i,j,k),turn(i,j-1,k-D),inf);
                if(j<Q) add(turn(i,j,k),turn(i,j+1,k-D),inf);
            }
}

bool bfs()
{
    for(int i=src;i<=decc;++i) lev[i]=-1,cur[i]=front[i];
    while(!q.empty()) q.pop();
    q.push(src);
    lev[src]=0;
    int now;
    while(!q.empty())
    {
        now=q.front();
        q.pop();
        for(int i=front[now];i;i=nxt[i])
            if(lev[to[i]]==-1 && cap[i])
            {
                lev[to[i]]=lev[now]+1;
                if(to[i]==decc) return true;
                q.push(to[i]);
            }
    }
    return false;
}

int dinic(int now,int flow)
{
    if(now==decc) return flow;
    int delta,rest=0;
    for(int &i=cur[now];i;i=nxt[i])
        if(lev[to[i]]==lev[now]+1 && cap[i])
        {
            delta=dinic(to[i],min(flow-rest,cap[i]));
            if(delta) 
            {
                rest+=delta;
                cap[i]-=delta; cap[i^1]+=delta;
                if(rest==flow) break;
            }
        }
    if(rest!=flow) lev[now]=-1;
    return rest;
}

void solve()
{
    int ans=0;
    while(bfs()) ans+=dinic(src,inf);
    printf("%d",ans); 
}

int main()
{
    freopen("cake.in","r",stdin);
    freopen("cake.out","w",stdout);
    init();
    build();
    solve();
}
View Code

 

3144: [Hnoi2013]切糕

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 2143  Solved: 1165
[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

posted @ 2017-12-15 22:33  TRTTG  阅读(190)  评论(0编辑  收藏  举报