fork(1) download
  1. #!/usr/bin/perl
  2. #!/usr/bin/perl
  3. use strict;
  4. use warnings;
  5.  
  6. my @I; # Исходная матрица
  7. my @W; # Рабочая матрица
  8. my ($MX,$MY); # Размеры матрицы
  9. while(<DATA>) { # Читаем исходую матрицу
  10. my @row=();
  11. last if(!$_);
  12. push @row, $_ for split / +/;
  13. push @I, \@row;
  14. $MX=@row; $MY++; # Запоминаем размеры
  15. my @row2=(); # И заполняем начальными значениями рабочую
  16. push @row2,10000 for(1..$MX);
  17. push @W, \@row2;
  18. }
  19. $MX--; $MY--;
  20. # обходим все 4 стороны прямоугольника
  21. cell(0,$_,0) for(1..$MY);
  22. cell($MX,$_,0) for(1..$MY);
  23. cell($_,0,0) for(1..$MX);
  24. cell($_,$MY,0) for(1..$MX);
  25.  
  26. # Печать результирующей матрицы и расчет объема воды
  27. my $summ=0;
  28. my $y=0;
  29. for(@W) {
  30. $,=" ";
  31. print "@$_\n";
  32. for my $x(0..$MX) { $summ+=$W[$y][$x]-$I[$y][$x]; }
  33. $y++;
  34. }
  35.  
  36. print "RESULT = $summ\n";
  37.  
  38. # Основная рабочая, рекурсивная функция
  39. sub cell {
  40. my($x, $y, $lev)=@_;
  41. return if($x<0 || $y<0 || $x>$MX || $y>$MY); # Проверяем выход за пределы поля
  42. return if($W[$y][$x]<=$lev); # Максимум клетки ниже или равен - мы тут были
  43. $lev=$I[$y][$x] if($lev < $I[$y][$x]); # Повышаем текущий уровень, если ниже изначального для клетки
  44. $W[$y][$x]=$lev; # Устанавливаем текущий максимум
  45. cell($x-1,$y,$lev); # И обходим всех 4х соседей рекурсивно
  46. cell($x+1,$y,$lev);
  47. cell($x,$y-1,$lev);
  48. cell($x,$y+1,$lev);
  49. }
  50.  
  51. __DATA__
  52. 5 3 4 5
  53. 6 2 1 4
  54. 3 1 1 4
  55. 8 5 5 3
  56. 8 3 1 6
  57. 8 4 5 8
  58.  
Success #stdin #stdout 0s 17768KB
stdin
Standard input is empty
stdout
5 3 4 5
6 3 3 4
3 3 3 4
8 5 5 3
8 4 4 6
8 4 5 8
RESULT = 11