位图,检查正交路径是否已关闭

时间:2013-02-05 20:35:31

标签: algorithm graphics 2d

给出了2d位数。

var map1 = [[0,0,0,0,0,0,0,0],
            [0,0,0,0,1,0,0,0],
            [0,0,1,1,1,1,1,0],
            [0,0,1,0,0,0,1,0],
            [0,0,1,1,0,0,1,0],
            [0,0,1,0,0,0,1,0],
            [0,0,1,1,1,1,1,0],
            [0,0,0,0,0,0,0,0]];

我如何通过编程方式检查某些“某些”是否正在形成封闭的路径?

http://jsfiddle.net/RvN3k/

两个左边的位图包含封闭的路径,上面的一个是明显的,下面的一个只是一个没有内部的封闭路径。

两个右边的位图不包含闭合路径,在上面的示例中,缺少一个位,在下面的示例中,一个对角线像素不计数,仅正交路径。

3 个答案:

答案 0 :(得分:1)

找到一个包含1的单元格,然后从那里“泛滥”。我的意思是:使用第二个映射,最初都设置为0.当遇到第一个映射时,将第二个映射中的单元格设置为1.现在检查所有相邻单元格,将第二个映射中的单元格设置为1在原始地图中也是1.一旦你尝试设置一个已经为1的单元格,你知道你遇到了一个封闭的路径;不要再检查那个细胞,否则你会得到一个无限循环。

编辑:如果您想要通过封闭路径连接到一个单元格的所有单元格的完整列表,则juts会将您在“泛洪”期间遇到的每个单元格添加到最初仅保存起始单元格的列表中。如果在某些时候您没有找到另一个要泛洪的单元格,则没有关闭的路径,您可以丢弃该列表。根据您是否希望链接位图中的小“存根”被视为路径的一部分,您将不得不进行一些分支,为每个分支引入新列表,如果它们相交则合并它们。

答案 1 :(得分:1)

我已经分道扬琴并添加了一个方法findCycle()。

var fill = function(map, x, y) {
    if (Math.min(x,y) >= 0 && Math.max(x,y) < mapSize && map[x][y] == 0) {
        map[x][y] = -1;
        for (var dx = -1; dx <=1; dx +=1) {
            for (var dy=-1; dy<=1; dy += 1) {
                fill(map, x+dx, y+dy);
            }
        }
    }
}

function detect(map) {
    for(var x = 0; x + 1 < mapSize; x++){
       for(var y = 0; y + 1 < mapSize; y++){
           if (map[x][y] == 0) {
               map[x][y] = -2;
               return;
           }
           else if (map[x][y]== 1 && map[x+1][y]==1 && map[x][y+1]== 1 && map[x+1][y+1]==1) {
               map[x][y] = -2;
               return;
           }
       }
    }
}

function findCycle(mapData) {
    for(var x = 0; x < mapSize; x++){
       for(var y = 0; y < mapSize; y++){
           if (mapData[x][y] == 0) {
               fill(mapData, x, y);
                detect(mapData);
               return;
           }
       }
    }
}

它找到第一个0.递归地用“-1”填充所有相邻的0。然后搜索从初始0开始无法到达的任何现有0。(同时搜索四个“1”(红色)正方形的正方形。

http://jsfiddle.net/bn6pa/1/

在找到循环的第一个点绘制一个黑色方块。

答案 2 :(得分:1)

这个怎么样:

for each cell that's set to 1
    set that cell to -1
    recursively look for neighbouring cells set to 1, and set them to -1
        if you find a neighbouring cell that is already set to -1, loop found
    clean-up (set all cells that are set to -1 to 0, they are no longer relevant)

这应该接近O(N)。

在这里,我已将其实现为小提琴,请查看here。你会注意到第四个例子是奇怪的:我没有解决问题,因为你的问题定义没有说明你是否想要最大可能的循环或任何。事实上,你只是想知道是否有一个循环,当你遇到浅蓝色像素时就知道了。