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