Search code examples
c++calgorithmcomplexity-theory

Find all puddles on the square (algorithm)


The problem is defined as follows: You're given a square. The square is lined with flat flagstones size 1m x 1m. Grass surround the square. Flagstones may be at different height. It starts raining. Determine where puddles will be created and compute how much water will contain. Water doesn't flow through the corners. In any area of ​​grass can soak any volume of water at any time.

Input:

width height

width*height non-negative numbers describing a height of each flagstone over grass level.

Output:

Volume of water from puddles.

width*height signs describing places where puddles will be created and places won't.

. - no puddle

# - puddle

Examples

Input:

8 8
0 0 0 0 0 1 0 0 
0 1 1 1 0 1 0 0
0 1 0 2 1 2 4 5 
0 1 1 2 0 2 4 5 
0 3 3 3 3 3 3 4 
0 3 0 1 2 0 3 4 
0 3 3 3 3 3 3 0 
0 0 0 0 0 0 0 0 

Output:

11
........
........
..#.....
....#...
........
..####..
........
........

Input:

16 16
8 0 1 0 0 0 0 2 2 4 3 4 5 0 0 2
6 2 0 5 2 0 0 2 0 1 0 3 1 2 1 2
7 2 5 4 5 2 2 1 3 6 2 0 8 0 3 2
2 5 3 3 0 1 0 3 3 0 2 0 3 0 1 1
1 0 1 4 1 1 2 0 3 1 1 0 1 1 2 0
2 6 2 0 0 3 5 5 4 3 0 4 2 2 2 1
4 2 0 0 0 1 1 2 1 2 1 0 4 0 5 1
2 0 2 0 5 0 1 1 2 0 7 5 1 0 4 3
13 6 6 0 10 8 10 5 17 6 4 0 12 5 7 6
7 3 0 2 5 3 8 0 3 6 1 4 2 3 0 3
8 0 6 1 2 2 6 3 7 6 4 0 1 4 2 1
3 5 3 0 0 4 4 1 4 0 3 2 0 0 1 0
13 3 6 0 7 5 3 2 21 8 13 3 5 0 13 7
3 5 6 2 2 2 0 2 5 0 7 0 1 3 7 5
7 4 5 3 4 5 2 0 23 9 10 5 9 7 9 8
11 5 7 7 9 7 1 0 17 13 7 10 6 5 8 10

Output:

103
................
..#.....###.#...
.......#...#.#..
....###..#.#.#..
.#..##.#...#....
...##.....#.....
..#####.#..#.#..
.#.#.###.#..##..
...#.......#....
..#....#..#...#.
.#.#.......#....
...##..#.#..##..
.#.#.........#..
......#..#.##...
.#..............
................

I tried different ways. Floodfill from max value, then from min value, but it's not working for every input or require code complication. Any ideas?

I'm interesting algorithm with complexity O(n^2) or o(n^3).


Solution

  • Summary

    I would be tempted to try and solve this using a disjoint-set data structure.

    The algorithm would be to iterate over all heights in the map performing a floodfill operation at each height.

    Details

    For each height x (starting at 0)

    1. Connect all flagstones of height x to their neighbours if the neighbour height is <= x (storing connected sets of flagstones in the disjoint set data structure)

    2. Remove any sets that connected to the grass

    3. Mark all flagstones of height x in still remaining sets as being puddles

    4. Add the total count of flagstones in remaining sets to a total t

    At the end t gives the total volume of water.

    Worked Example

    0 0 0 0 0 1 0 0 
    0 1 1 1 0 1 0 0
    0 1 0 2 1 2 4 5 
    0 1 1 2 0 2 4 5 
    0 3 3 3 3 3 3 4 
    0 3 0 1 2 0 3 4 
    0 3 3 3 3 3 3 0 
    0 0 0 0 0 0 0 0 
    

    Connect all flagstones of height 0 into sets A,B,C,D,E,F

    A A A A A 1 B B 
    A 1 1 1 A 1 B B
    A 1 C 2 1 2 4 5 
    A 1 1 2 D 2 4 5 
    A 3 3 3 3 3 3 4 
    A 3 E 1 2 F 3 4 
    A 3 3 3 3 3 3 A 
    A A A A A A A A 
    

    Remove flagstones connecting to the grass, and mark remaining as puddles

              1      
      1 1 1   1
      1 C 2 1 2 4 5     #
      1 1 2 D 2 4 5       #
      3 3 3 3 3 3 4 
      3 E 1 2 F 3 4     #     #
      3 3 3 3 3 3 
    

    Count remaining set size t=4

    Connect all of height 1

              G      
      C C C   G
      C C 2 D 2 4 5     #
      C C 2 D 2 4 5       #
      3 3 3 3 3 3 4 
      3 E E 2 F 3 4     #     #
      3 3 3 3 3 3 
    

    Remove flagstones connecting to the grass, and mark remaining as puddles

          2   2 4 5     #
          2   2 4 5       #
      3 3 3 3 3 3 4 
      3 E E 2 F 3 4     # #   #
      3 3 3 3 3 3 
    

    t=4+3=7

    Connect all of height 2

          A   B 4 5     #
          A   B 4 5       #
      3 3 3 3 3 3 4 
      3 E E E E 3 4     # #   #
      3 3 3 3 3 3 
    

    Remove flagstones connecting to the grass, and mark remaining as puddles

                4 5     #
                4 5       #
      3 3 3 3 3 3 4 
      3 E E E E 3 4     # # # #
      3 3 3 3 3 3 
    

    t=7+4=11

    Connect all of height 3

                4 5     #
                4 5       #
      E E E E E E 4 
      E E E E E E 4     # # # #
      E E E E E E 
    

    Remove flagstones connecting to the grass, and mark remaining as puddles

                4 5     #
                4 5       #
                  4 
                  4     # # # #
    

    After doing this for heights 4 and 5 nothing will remain.

    A preprocessing step to create lists of all locations with each height should mean that the algorithm is close to O(n^2).