在乳蛋糕沼泽拼图中的小精灵

时间:2009-05-21 18:38:58

标签: algorithm language-agnostic logic puzzle lower-bound

(感谢Rich Bradshaw)

我正在寻找以下谜题的最佳策略。

作为新的仙女王,你有责任绘制王国的蛋羹沼泽 沼泽被一片飘渺的薄雾覆盖着,整个乳蛋糕岛都散落着 您可以将您的小精灵发送到沼泽地,并指示在每个点飞低或高 如果一个小精灵猛扑过乳蛋糕,那么它会分散注意力并且不会完成它的序列。 由于雾很浓,所有你知道的是小精灵是否到了另一边。

编码方面..

bool flutter( bool[size] swoop_map ); 

这将返回一个小精灵是否退出给定的猛扑序列。

最简单的方法是只用一次猛扑传递序列。这揭示了所有“大小”尝试的蛋羹岛 我宁愿与蛋羹的数量成比例的东西 - 但是像以下序列有问题:

     C......C     (that is, custards at beginning and end) 

也欢迎链接到其他形式的这个难题。

2 个答案:

答案 0 :(得分:2)

布莱恩的第一个分治算法在以下意义上是最优的:存在一个常数C,使得在所有具有n个正方形和最多k个术语的沼泽中,没有算法的最坏情况比布莱恩的C超过C倍。 。 Brian的算法使用O(k log(n / k))次数,这是一个常数因子,log2的信息理论下界(n选择k)> = log2((n / k)^ k)= k欧米茄(k log(n / k))。 (您需要像k <= n / 2这样的假设才能使最后一步严格,但此时,我们已经达到了O(n)航班的最大值。)

为什么Brian的算法仅使用O(k log(n / k))航班?在递归深度i处,它最多可以进行最小(2 ^ i,k)次飞行。 0 <= i <= log2(k)的和是O(k)。 log2(k)&lt; i&lt; = log2(n)是k(log2(n) - log2(k))= k(log2(n / k))。

答案 1 :(得分:2)

这让我想到分而治之。也许这样的事情(这是一个稍微破碎的伪代码。它可能有栅栏后错误等):

retval[size] check()
{
   bool[size] retval = ALLFALSE;
   bool[size] flut1 = ALLFALSE;
   bool[size] flut2 = ALLFALSE;
   for (int i = 0; i < size/2; ++i) flut1[i] = TRUE;
   for (int i = size/2; i < size; ++i) flut2[i] = TRUE;
   if (flutter(flut1)) retval[0..size/2] = <recurse>check
   if (flutter(flut2)) retval[size/2..size] = <recurse>check
}

用简单的英语,它会在奶油蛋白图的每一半上调用颤抖。如果任何一半返回false,则整半都没有蛋羹。否则,一半的一半具有递归应用的算法。我不确定是否有可能做得更好。但是,如果沼泽主要是蛋羹,那么这种算法有点蹩脚。

理念二:

int itsize = 1
bool[size] retval = ALLFALSE;
for (int pos = 0; pos < size;)
{
    bool[size] nextval = ALLFALSE;
    for (int pos2 = pos; pos2 < pos + size && pos2 < size; ++pos2) nextval[pos2] = true;
    bool flut = flutter(nextval)
    if (!flut || itsize == 1)
    {
        for (int pos2 = pos; pos2 < pos + size && pos2 < size; ++pos2) retval[pos2] = flut;
        pos+=itsize;
    }
    if (flut) itsize = 1;
    if (!flut) itsize*=2;
}

用简单的英语,它会调用乳蛋糕地图的每个元素,一次一个。如果没有找到蛋羹,则下一个呼叫将是前一次呼叫的两倍。这有点像二进制搜索,只是在一个方向上,因为它不知道它搜索了多少项。我不知道这是多么有效。