题目描述 Description
经过千辛万苦小 A 得到了一块切糕,切糕的形状是长方体,小 A 打算拦腰将切糕切成两半分给小 B。出于美观考虑,小 A 希望切面能尽量光滑且和谐。于是她找到你,希望你能帮她找出最好的切割方案。
出于简便考虑,我们将切糕视作一个长 P、宽 Q、高 R 的长方体点阵。我们将位于第 z层中第 x 行、第 y 列上(1≤x≤P, 1≤y≤Q, 1≤z≤R)的点称为(x,y,z),它有一个非负的不和谐值 v(x,y,z)。一个合法的切面满足以下两个条件:
1. 与每个纵轴(一共有 P*Q 个纵轴)有且仅有一个交点。即切面是一个函数 f(x,y),对于所有 1≤x≤P, 1≤y≤Q,我们需指定一个切割点 f(x,y),且 1≤f(x,y)≤R。
2. 切面需要满足一定的光滑性要求,即相邻纵轴上的切割点不能相距太远。对于所有的 1≤x,x’≤P 和 1≤y,y’ ≤Q,若|x-x’|+|y-y’|=1,则|f(x,y)-f(x’,y’)| ≤D,其中 D 是给定的一个非负整数。
可能有许多切面f 满足上面的条件,小A 希望找出总的切割点上的不和谐值最小的那个,即 ∑v(x,y, f(x,y))最小。
输入描述 Input Description
输入文件第一行是三个正整数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)。
输出描述 Output Description
输出仅包含一个整数,表示在合法基础上最小的总不和谐值。
样例输入 Sample Input
input1
2 2 2
1
6 1
6 1
2 6
2 6
input2
2 2 2
0
5 1
5 1
2 5
2 5
样例输出 Sample Output
output1
6
output2
12
数据范围及提示 Data Size & Hint
100%的数据满足P,Q,R≤40,0≤D≤R,且给出的所有的不和谐值不超过1000。
终于AC了
弱爆了,调一个网络流都调了一上午,各种异常错误应有尽有
这是一个很巧妙的网络流最小割,每一个竖列都要切一个点,所以最开始我们从上一直连到下面
但是还有第二个条件,相邻的两个点高度差不能超过D
先不管它
我们现在求出了一个最大流,但是不满足第二个条件
所以我们对于每一个点(x,y,z)都向(x-d,y,z)的相邻的4个点连一条无穷大的边,使这种情况不是最大流
然后就是套网络流的模板了
1 var 2 map:array[0..70000,-5..5]of longint; 3 dis,his,pre:array[0..70000]of longint; 4 vh:array[0..70000]of longint; 5 fx:array[-5..5]of longint; 6 a,b,c,d,flow:longint; 7 8 procedure init; 9 var 10 i,j,k:longint; 11 begin 12 read(b,c,a,d); 13 for i:=1 to a do 14 for j:=1 to b do 15 for k:=1 to c do 16 begin 17 read(map[(i-1)*b*c+(j-1)*c+k,1]); 18 if i>d then 19 begin 20 if k>1 then map[(i-1)*b*c+(j-1)*c+k,2]:=100000000; 21 if j>1 then map[(i-1)*b*c+(j-1)*c+k,3]:=100000000; 22 if k<c then map[(i-1)*b*c+(j-1)*c+k,4]:=100000000; 23 if j<b then map[(i-1)*b*c+(j-1)*c+k,5]:=100000000; 24 end; 25 end; 26 fx[1]:=b*c; 27 fx[2]:=-d*b*c-1; 28 fx[3]:=-d*b*c-c; 29 fx[4]:=-d*b*c+1; 30 fx[5]:=-d*b*c+c; 31 for i:=1 to 5 do 32 fx[-i]:=-fx[i]; 33 end; 34 35 function max(x,y:longint):longint; 36 begin 37 if x>y then exit(x); 38 exit(y); 39 end; 40 41 procedure work; 42 var 43 i,j,aug,min:longint; 44 flag:boolean; 45 begin 46 vh[0]:=a*b*c+2; 47 i:=0; 48 aug:=maxlongint; 49 while dis[0]<=a*b*c+1 do 50 begin 51 flag:=false; 52 his[i]:=aug; 53 if i=0 then 54 begin 55 for j:=1 to b*c do 56 if dis[0]=dis[j]+1 then 57 begin 58 flag:=true; 59 pre[j]:=-1; 60 break; 61 end; 62 if flag then i:=j; 63 end 64 else 65 for j:=-5 to 5 do 66 if i+fx[j]>0 then 67 if (map[i,j]>0)and(dis[i]=dis[i+fx[j]]+1) then 68 begin 69 flag:=true; 70 pre[i+fx[j]]:=-j; 71 if aug>map[i,j] then aug:=map[i,j]; 72 inc(i,fx[j]); 73 if i>a*b*c then 74 begin 75 inc(flow,aug); 76 while i<>0 do 77 begin 78 inc(map[i,pre[i]],aug); 79 dec(map[max(i+fx[pre[i]],0),-pre[i]],aug); 80 inc(i,fx[pre[i]]); 81 if i<0 then i:=0; 82 end; 83 aug:=maxlongint; 84 end; 85 break; 86 end; 87 if flag then continue; 88 min:=a*b*c+1; 89 if i=0 then 90 begin 91 for j:=1 to b*c do 92 if min>dis[j] then min:=dis[j]; 93 end 94 else 95 for j:=-5 to 5 do 96 if i+fx[j]>0 then 97 if (map[i,j]>0)and(dis[i+fx[j]]<min) then min:=dis[i+fx[j]]; 98 dec(vh[dis[i]]); 99 if vh[dis[i]]=0 then break; 100 dis[i]:=min+1; 101 inc(vh[dis[i]]); 102 if i<>0 then 103 begin 104 inc(i,fx[pre[i]]); 105 if i<0 then i:=0; 106 aug:=his[i]; 107 end; 108 end; 109 write(flow); 110 end; 111 112 begin 113 init; 114 work; 115 end.