• 3144:[HNOI2013]切糕


    题目描述 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 
    6 1 
    6 1 
    2 6 
    2 6 
    input2 
    2 2 2 
    5 1 
    5 1 
    2 5 
    2 5
    样例输出 Sample Output
    output1
    output2
    12
    数据范围及提示 Data Size & Hint
    100%的数据满足P,Q,R≤40,0≤D≤R,且给出的所有的不和谐值不超过1000。 
     
     
    终于AC了
    弱爆了,调一个网络流都调了一上午,各种异常错误应有尽有
    这是一个很巧妙的网络流最小割,每一个竖列都要切一个点,所以最开始我们从上一直连到下面
    但是还有第二个条件,相邻的两个点高度差不能超过D
    先不管它
    我们现在求出了一个最大流,但是不满足第二个条件
    3144:[HNOI2013]切糕 <wbr>- <wbr>BZOJ
    所以我们对于每一个点(x,y,z)都向(x-d,y,z)的相邻的4个点连一条无穷大的边,使这种情况不是最大流
    3144:[HNOI2013]切糕 <wbr>- <wbr>BZOJ
    然后就是套网络流的模板了
     
      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.
    View Code
  • 相关阅读:
    php函数
    php循环语句(二)
    php循环语句(一)
    php魔术常量
    php超级全局变量
    php数组函数
    php数组
    php条件语句(二)
    php条件语句(一)
    shell 中的判断
  • 原文地址:https://www.cnblogs.com/Randolph87/p/3582396.html
Copyright © 2020-2023  润新知