简单递归算法中终止路径的问题

时间:2010-08-19 22:55:14

标签: java algorithm recursion

首先:这不是家庭作业,而是属于我的业余爱好项目。

背景 对于我的Java益智游戏,我使用一个非常简单的递归算法来检查“地图”上的某些空格是否在放置一块之后变得孤立。在这种情况下隔离意味着:没有任何部件可以放入。

当前算法:

public int isolatedSpace(Tile currentTile, int currentSpace){
        if(currentTile != null){
            if(currentTile.isOpen()){
                currentTile.flag(); // mark as visited
                currentSpace += 1;
                currentSpace = isolatedSpace(currentTile.rightNeighbor(),currentSpace);
                currentSpace = isolatedSpace(currentTile.underNeighbor(),currentSpace);
                currentSpace = isolatedSpace(currentTile.leftNeighbor(),currentSpace);
                currentSpace = isolatedSpace(currentTile.upperNeighbor(),currentSpace);
                if(currentSpace < 3){currentTile.markAsIsolated();} // <-- the problem
            }
        }
        return currentSpace;
    }

这段代码返回起始tile所属的空白空间的大小。代码的那部分工作是有意的。但是我遇到了关于标记瓷砖的问题,这就是使这个问题的标题相关的原因;)

问题: 问题是某些磁贴永远不会“重新访问”(它们会返回一个值并终止,因此永远不会从后来的版本中获取返回值来更新空白区域的大小)。这些“遗忘”的磁贴可以是大空间的一部分,但仍然标记为隔离,因为当 currentSpace 值较低时,它们在进程开始时被访问过。

问题: 如何改进此代码,以便为瓷砖设置正确的值而不会产生太多开销?我可以想到丑陋的解决方案,比如重新访问所有标记的磁贴,如果它们具有正确的值,则检查邻居是否具有相同的值,如果没有更新等等。但我确信Stack Overflow上有很多优秀的人有更好的想法; )


更新 我做了一些改变。

public int isolatedSpace(Tile currentTile, int currentSpace, LinkedList<Tile> visitedTiles){
        if(currentTile != null){
            if(currentTile.isOpen()){
                // do the same as before
                visitedTiles.add(); 
            }
        }
        return currentSpace;
    }

标记函数(仅在返回的spaceize小于给定值时调用)

marktiles(visitedTiles){
       for(Tile t : visitedTiles){
            t.markAsIsolated();
       }
}

这种方法符合雷克斯克尔的答案,至少如果我理解他的想法。

2 个答案:

答案 0 :(得分:2)

这不是一般解决方案,但如果它们出现在两个或更少空格的区域中,则只将空格标记为已隔离。你不能简化这个测试,“如果(a)它没有开放的邻居或者(b)恰好是一个开放的邻居,而且该邻居没有其他开放的邻居,那么这个空间是孤立的。”

答案 1 :(得分:1)

您需要有两个步骤:收集有关空间是否隔离的信息,然后单独标记为隔离。因此,您需要首先计算所有空间(使用一个递归函数),然后在标准通过时标记所有连接的空格(使用不同的递归函数)。