这里引用一下别人的题解
最小割模型,非常好的题目
3144: [Hnoi2013]切糕
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
http://blog.csdn.net/zarxdy34/article/details/45272055
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define maxn 50
#define Node(k, i, j) ((k - 1) * P * Q + (i - 1) * Q + j)
using namespace std;
int P, Q, R, D;
int a[maxn][maxn][maxn];
int S, T;
struct Edge{
int to, next, w;
}edge[2000010];
int cnt = 1, h[100010];
void add(int u, int v, int w){
cnt ++;
edge[cnt].to = v;
edge[cnt].next = h[u];
edge[cnt].w = w;
h[u] = cnt;
swap(u, v);w = 0;
cnt ++;
edge[cnt].to = v;
edge[cnt].next = h[u];
edge[cnt].w = w;
h[u] = cnt;
}
const int dx[] = {0, 0, -1, 1};
const int dy[] = {1, -1, 0, 0};
const int inf = 0x7fffffff;
bool isinit(int x, int y){
return x > 0 && y > 0 && x <= P && y <= Q;
}
queue<int>q;
int d[100010];
bool BFS(){
q.push(S);
memset(d, -1, sizeof d);
d[S] = 0;
while(!q.empty()){
int u = q.front();q.pop();
for(int i = h[u]; i; i = edge[i].next){
if(!edge[i].w)continue;
int v = edge[i].to;
if(d[v] == -1){
d[v] = d[u] + 1;
q.push(v);
}
}
}return d[T] != -1;
}
int DFS(int x, int a){
if(a == 0 || x == T)return a;
int used = 0, f;
for(int i = h[x]; i; i = edge[i].next){
int v = edge[i].to;
if(d[v] == d[x] + 1){
f = DFS(v, min(edge[i].w, a - used));
edge[i].w -= f;
edge[i ^ 1].w += f;
used += f;
if(used == a)return used;
}
}
if(!used)d[x] = -1;
return used;
}
void Dinic(){
int ret = 0;
while(BFS())
ret += DFS(S, inf);
printf("%d\n", ret);
}
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", &a[i][j][k]);
S = 0, T = P * Q * R + 1;
int n = P, m = Q;
for(int i = 1; i <= n; i ++){
for(int j = 1; j <= m; j ++){
add(S, Node(1, i, j), a[1][i][j]);
add(Node(R, i, j), T, inf);
for(int k = 2; k <= R; k ++){
add(Node(k - 1, i, j), Node(k, i, j), a[k][i][j]);
if(k <= D)continue;
for(int p = 0; p < 4; p ++){
int u = i + dx[p], v = j + dy[p];
if(!isinit(u, v))continue;
add(Node(k, i, j), Node(k - D, u, v), inf);
}
}
}
}
Dinic();
return 0;
}