3144: [Hnoi2013]切糕
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 915 Solved: 511
[ 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
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
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <algorithm>
#define LL long long
using namespace std;
const int MAXN = 64000 + 10;
const int INF = 0x7fffffff;
struct Edge{int to, next, cap, flow;}edge[MAXN<<2];
int tot, head[MAXN];
int gap[MAXN], dep[MAXN], pre[MAXN], cur[MAXN];
void init(){tot = 0; memset(head, -1, sizeof(head));}
void addedge(int u, int v, int w, int rw = 0)
{
edge[tot].to = v; edge[tot].cap = w; edge[tot].next = head[u];
edge[tot].flow = 0; head[u] = tot++;
edge[tot].to = u; edge[tot].cap = rw; edge[tot].next = head[v];
edge[tot].flow = 0; head[v] = tot++;
}
long long sap(int start, int end, int N)
{
memset(gap, 0, sizeof(gap));
memset(dep, 0, sizeof(dep));
memcpy(cur, head, sizeof(head));
int u = start; pre[u] = -1; gap[0] = N; long long ans = 0;
while(dep[start] < N)
{
if(u == end)
{
long long Min = INF;
for(int i=pre[u];i!=-1;i=pre[edge[i^1].to])
if(Min > edge[i].cap - edge[i].flow)
Min = edge[i].cap - edge[i].flow;
for(int i=pre[u];i!=-1;i=pre[edge[i^1].to])
{
edge[i].flow += Min;
edge[i^1].flow -= Min;
}
u = start; ans += Min; continue;
}
bool flag = false; int v;
for(int i=cur[u];i!=-1;i=edge[i].next)
{
v = edge[i].to;
if(edge[i].cap - edge[i].flow && dep[v] + 1 == dep[u])
{
flag = true;
cur[u] = pre[v] = i;
break;
}
}
if(flag){u = v; continue;}
int Min = N;
for(int i=head[u];i!=-1;i=edge[i].next)
if(edge[i].cap - edge[i].flow && dep[edge[i].to] < Min)
{
Min = dep[edge[i].to];
cur[u] = i;
}
gap[dep[u]]--;
if(!gap[dep[u]]) return ans;
dep[u] = Min + 1;
gap[dep[u]]++;
if(u != start) u = edge[pre[u]^1].to;
}
return ans;
}
int f[50][50][50], P, Q, R, D;
int dir[][2] = {{-1, 0}, {1, 0}, {0, 1}, {0, -1}};
int cal(int x, int y, int z)
{
if(z == 0) return 0;
return (z - 1) * P * Q + (x - 1) * Q + y;
}
int main()
{
init();
scanf("%d%d%d", &P, &Q, &R);
scanf("%d", &D);
for(int z=1;z<=R;z++)
{
for(int x=1;x<=P;x++)
{
for(int y=1;y<=Q;y++)
scanf("%d", &f[x][y][z]);
}
}
int T = P * Q * R + 1;
for(int x=1;x<=P;x++)
{
for(int y=1;y<=Q;y++)
{
for(int z=1;z<=R;z++)
{
addedge(cal(x, y, z-1), cal(x, y, z), f[x][y][z]);
if(z > D)
{
for(int k=0;k<4;k++)
{
int nx = x + dir[k][0], ny = y + dir[k][1];
if(nx < 1 || nx > P || ny < 1 || ny > Q) continue;
addedge(cal(x, y, z), cal(nx, ny, z - D), INF);
}
}
}
addedge(cal(x, y, R), T, INF);
}
}
long long ans = sap(0, T, T + 1);
printf("%lld\n", ans);
return 0;
}