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.  
  21. cell(0,1,0);
  22.  
  23. # Печать результирующей матрицы и расчет объема воды
  24. my $summ=0;
  25. my $y=0;
  26. for(@W) {
  27. $,=" ";
  28. print "@$_\n";
  29. for my $x(0..$MX) { $summ+=$W[$y][$x]-$I[$y][$x]; }
  30. $y++;
  31. }
  32.  
  33. print "RESULT = $summ\n";
  34.  
  35. # Основная рабочая, рекурсивная функция
  36. sub cell {
  37. my($x, $y, $lev)=@_;
  38. return if($x<0 || $y<0 || $x>$MX || $y>$MY); # Проверяем выход за пределы поля
  39. return if($W[$y][$x]<=$lev); # Максимум клетки ниже или равен - мы тут были
  40. if($lev < $I[$y][$x] || # Повышаем текущий уровень, если ниже изначального для клетки
  41. ($x==0 || $y==0 || $x==$MX || $y==$MY) # Или если выше, но это граничная клетка
  42. ) {
  43. $lev=$I[$y][$x]
  44. }
  45. $W[$y][$x]=$lev; # Устанавливаем текущий максимум
  46. cell($x-1,$y,$lev); # И обходим всех 4х соседей рекурсивно
  47. cell($x+1,$y,$lev);
  48. cell($x,$y-1,$lev);
  49. cell($x,$y+1,$lev);
  50. }
  51.  
  52. __DATA__
  53. 5 3 4 5
  54. 6 2 1 4
  55. 3 1 1 4
  56. 8 5 5 3
  57. 8 3 1 6
  58. 8 4 5 8
  59.  
Success #stdin #stdout 0s 18248KB
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