Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/141.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 查找正方形上的所有水坑(算法)_C++_C_Algorithm_Complexity Theory - Fatal编程技术网

C++ 查找正方形上的所有水坑(算法)

C++ 查找正方形上的所有水坑(算法),c++,c,algorithm,complexity-theory,C++,C,Algorithm,Complexity Theory,问题定义如下: 给你一个正方形。广场两旁是尺寸为1m x 1m的平坦石板。广场四周长满了草。石板可能在不同的高度。开始下雨了。确定将在何处形成水坑,并计算将包含多少水。水不会从拐角处流过。在任何领域​​草可以在任何时间浸泡任何体积的水 输入: 宽高 宽度*高度非负数,用于描述草地上每个石板的高度 输出: 水坑中的水量 宽度*高度标志,描述将形成水坑和不会形成水坑的位置 .-没有水坑 #-水坑 例子 输入: 8 8 0 0 0 0 0 1 0 0 0 1 1 1 0 1 0 0 0 1 0 2

问题定义如下: 给你一个正方形。广场两旁是尺寸为1m x 1m的平坦石板。广场四周长满了草。石板可能在不同的高度。开始下雨了。确定将在何处形成水坑,并计算将包含多少水。水不会从拐角处流过。在任何领域​​草可以在任何时间浸泡任何体积的水

输入: 宽高

宽度*高度非负数,用于描述草地上每个石板的高度

输出: 水坑中的水量

宽度*高度标志,描述将形成水坑和不会形成水坑的位置

.-没有水坑

#-水坑

例子 输入:

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 
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
输出:

11
........
........
..#.....
....#...
........
..####..
........
........
103
................
..#.....###.#...
.......#...#.#..
....###..#.#.#..
.#..##.#...#....
...##.....#.....
..#####.#..#.#..
.#.#.###.#..##..
...#.......#....
..#....#..#...#.
.#.#.......#....
...##..#.#..##..
.#.#.........#..
......#..#.##...
.#..............
................
输入:

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 
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
输出:

11
........
........
..#.....
....#...
........
..####..
........
........
103
................
..#.....###.#...
.......#...#.#..
....###..#.#.#..
.#..##.#...#....
...##.....#.....
..#####.#..#.#..
.#.#.###.#..##..
...#.......#....
..#....#..#...#.
.#.#.......#....
...##..#.#..##..
.#.#.........#..
......#..#.##...
.#..............
................
我试过不同的方法。从最大值开始,然后从最小值开始进行泛洪填充,但它不适用于每个输入或需要复杂的代码。有什么想法吗

我对复杂度为O(n^2)或O(n^3)的算法很感兴趣。

Summary 我很想尝试用一个简单的方法来解决这个问题

该算法将迭代地图中的所有高度,在每个高度执行洪水填充操作

细节 对于每个高度x(从0开始)


  • 将所有x高的石板连接到相邻石板上,如果相邻石板的高度,这似乎很有效。其思想是,它是一个递归函数,检查是否有“向外流动”允许它逃逸到边缘。如果没有这样的值,则逃逸将陷入泥潭。我在你的两个输入文件上进行了测试,效果很好。我为您复制了这两个文件的输出。请原谅我对全局变量的恶劣使用,我认为算法背后的概念很重要,不是好的风格:)

    8乘8文件

    11111111
    11111111
    11011111
    11110111
    11111111
    11000011
    11111111
    11111111
    
    通过做几件事,您可以轻松且显著地优化此算法。答:找到路线后立即返回true将大大加快速度。您还可以将其全局连接到当前结果集,以便任何给定点只需找到到已知流动点的流动点,而不必一直到边缘

    在所涉及的工作中,每个n将必须检查每个节点。然而,通过优化,我们应该能够在大多数情况下得到比n^2低得多的结果,但在最坏的情况下,它仍然是一个n^3算法。。。但创建这一点将非常困难(使用适当的优化逻辑…动态规划以实现双赢!)

    编辑:

    修改后的代码适用于以下情况:

    8 8
    1 1 1 1 1 1 1 1
    1 0 0 0 0 0 0 1
    1 0 1 1 1 1 0 1
    1 0 1 0 0 1 0 1
    1 0 1 1 0 1 0 1
    1 0 1 1 0 1 0 1
    1 0 0 0 0 1 0 1
    1 1 1 1 1 1 1 1
    
    结果如下:

    11111111
    10000001
    10111101
    10100101
    10110101
    10110101
    10000101
    11111111
    
    现在,当我们移除底部的1时,我们希望看到没有水坑

    8 8
    1 1 1 1 1 1 1 1
    1 0 0 0 0 0 0 1
    1 0 1 1 1 1 0 1
    1 0 1 0 0 1 0 1
    1 0 1 1 0 1 0 1
    1 0 1 1 0 1 0 1
    1 0 0 0 0 1 0 1
    1 1 1 1 1 1 0 1
    
    这就是结果

    1 1 1 1 1 1 1 1
    1 1 1 1 1 1 1 1
    1 1 1 1 1 1 1 1
    1 1 1 1 1 1 1 1
    1 1 1 1 1 1 1 1
    1 1 1 1 1 1 1 1
    1 1 1 1 1 1 1 1
    1 1 1 1 1 1 1 1
    

    提示:计算最小生成树。但,如何将正方形转换为图形?每个石板的顶点?我猜石板高度之间每个边的权重是不同的。但我仍然不明白MST是如何找到所有水坑并计算水的体积的。@Davidisenstat你能详细说明一下如何清除那些不会被填满的石板石吗,因为有一种方法可以让水逸出?我认为这不起作用,因为在某些情况下,流向边缘的流量可能需要加倍(考虑一个由1组成的螺旋)你可能是对的,但是对于“加倍回”的问题,它需要一个不同的解决方案。与其“接近”初始值,不如不检查已经检查过的值。这名义上会增加内存需求,没有更复杂的计算。谢谢:)看起来很好,但是没有计算水的体积。这是必需的。谢谢:)我考虑过这种方法,但对于某些输入,例如1000000000100000000010000000001000000000,它运行得非常慢
        #include <fstream>
    #include <iostream>
    #include <vector>
    using namespace std;
    
    int SIZE_X;
    int SIZE_Y;
    
    
    bool **result;
    int **INPUT;
    
    
    bool flowToEdge(int x, int y, int value, bool* visited) {
        if(x < 0 || x == SIZE_X || y < 0 || y == SIZE_Y) return true;
        if(visited[(x * SIZE_X) + y]) return false;
        if(value < INPUT[x][y]) return false;
    
        visited[(x * SIZE_X) + y] = true;
    
        bool left = false;
        bool right = false;
        bool up = false;
        bool down = false;
    
    
        left = flowToEdge(x-1, y, value, visited);
        right = flowToEdge(x+1, y, value, visited);
        up = flowToEdge(x, y+1, value, visited);
        down = flowToEdge(x, y-1, value, visited);
    
    
        return (left || up || down || right);
    }
    
    int main() {
    
        ifstream myReadFile;
        myReadFile.open("test.txt");
    
        myReadFile >> SIZE_X;
        myReadFile >> SIZE_Y;
    
        INPUT = new int*[SIZE_X];
        result = new bool*[SIZE_X];
        for(int i = 0; i < SIZE_X; i++) {
            INPUT[i] = new int[SIZE_Y];
            result[i] = new bool[SIZE_Y];
            for(int j = 0; j < SIZE_Y; j++) {
                int someInt;
                myReadFile >> someInt;
                INPUT[i][j] = someInt;
                result[i][j] = false;
            }
        }
    
    
        for(int i = 0; i < SIZE_X; i++) {
            for(int j = 0; j < SIZE_Y; j++) {
                bool visited[SIZE_X][SIZE_Y];
                for(int k = 0; k < SIZE_X; k++)//You can avoid this looping by using maps with pairs of coordinates instead
                    for(int l = 0; l < SIZE_Y; l++)
                        visited[k][l] = 0;
    
                result[i][j] = flowToEdge(i,j, INPUT[i][j], &visited[0][0]);
            }
        }
    
        for(int i = 0; i < SIZE_X; i++) {
            cout << endl;
            for(int j = 0; j < SIZE_Y; j++)
                cout << result[i][j];
        }
        cout << endl;
    }
    
    1111111111111111
    1101111100010111
    1111111011101011
    1111000110101011
    1011001011101111
    1110011111011111
    1100000101101011
    1010100010110011
    1110111111101111
    1101101011011101
    1010111111101111
    1110011010110011
    1010111111111011
    1111110110100111
    1011111111111111
    1111111111111111
    
    11111111
    11111111
    11011111
    11110111
    11111111
    11000011
    11111111
    11111111
    
    8 8
    1 1 1 1 1 1 1 1
    1 0 0 0 0 0 0 1
    1 0 1 1 1 1 0 1
    1 0 1 0 0 1 0 1
    1 0 1 1 0 1 0 1
    1 0 1 1 0 1 0 1
    1 0 0 0 0 1 0 1
    1 1 1 1 1 1 1 1
    
    11111111
    10000001
    10111101
    10100101
    10110101
    10110101
    10000101
    11111111
    
    8 8
    1 1 1 1 1 1 1 1
    1 0 0 0 0 0 0 1
    1 0 1 1 1 1 0 1
    1 0 1 0 0 1 0 1
    1 0 1 1 0 1 0 1
    1 0 1 1 0 1 0 1
    1 0 0 0 0 1 0 1
    1 1 1 1 1 1 0 1
    
    1 1 1 1 1 1 1 1
    1 1 1 1 1 1 1 1
    1 1 1 1 1 1 1 1
    1 1 1 1 1 1 1 1
    1 1 1 1 1 1 1 1
    1 1 1 1 1 1 1 1
    1 1 1 1 1 1 1 1
    1 1 1 1 1 1 1 1