探索一种算法来查找包含某些项目的最小链

时间:2012-10-21 15:30:24

标签: algorithm tuples bag

抱歉,我无法提出以下算法的算法名称或问题。我将陈述问题,然后我尝试过,也许有人可以指出我正确的方向。

想象一下你有一袋物品(无序,重复允许)。在实践中,袋子可能包含2-20个物品,以防松弛。

目标是找到最小长度链(如果我们有不同的链概念,有序链接列表),其中包含任何顺序的包中的所有项目。

一个链包含一个开始标记(不包含在包中),后跟任意数量的项目,后跟一个结束标记(也不在包中)。

通过将n元组拼接在一起形成链(顺序很重要),作为进一步的放松,让我们说n值对于所有元组都是相同的。在实践中,我正在使用n = 3.链条可以“混合”而不是连接,如果它们具有重叠元素。例如,考虑(a,b,c)和(c,d,e)。可以作为(a,b,c,d,e)连接。同样地,(a,b,c)和(b,c,d)可以连接为(a,b,c,d)。一些元组可能在第一个位置有一个开始标记,而一些标记在最后一个位置有一个结束标记,这当然可以解决问题。

因此,在我看来,问题的确切解决方案一般不易处理。为了获得问题的“好”解决方案,需要某种优化算法。我可以忍受的“好”解决方案。

我开始使用的是一种贪婪的方法,在第一遍中,你会发现包含袋中元素数量最多的元组,任意断开关系。创建一个数据结构,它保存我们迄今为止构建的链,并将选定的元组粘贴到此数据结构中。将问题拆分为2个子问题,即开始令牌侧和结束令牌侧。在子问题1的数据结构的第一个标记是起始标记并且子问题2的最后一个标记是结束标记之前,增长链以使我们尽快找到停止条件(开始或结束标记取决于在子问题上,同时也试图尽快排出袋子的内容。这可能不太好,因为每个子问题必须相互沟通,以确定需要包含多少物品。

有人在任何地方看到过这个问题吗有关如何改进(或正常工作)此算法的任何想法?这是我正在解决的一个真正的问题,它是一个更大系统的智能部分,不是玩具问题或家庭作业问题。

修改

对不起,我今天一直都不在电脑前。我将尝试发布一个示例解决方案,该解决方案不是太微不足道,但也不会太复杂,无法看到。

假设:

  1. Bag = {A, B, C, D} (为了示例,我将其设为一组,但每个项目可以出现多次)
  2. / = Start Token
  3. \ = End Token
  4. 3元组(三元组):为了简化命名,我将它们标记为a-g。小写字母在问题中没有实际功能。

    (/,A, E) a
    (/,C, D) b
    (/,G, H) c
    (D,B, A) d
    (C,G, H) e
    (B,A, \) f
    (G,H, \) g
    
  5. 解决方案:如果我们将b,d和f链接在一起,我们得到(/,C,D,B,A,\) 这是包含包中所有元素的最短链,如果计算开始和结束标记,则该长度为6。通常,最短路径的长度为| BAG | + 2,如果它确实存在。我希望我的问题陈述现在更有意义。

1 个答案:

答案 0 :(得分:2)

由于您最多只有20个项目,我认为您可以在合理的时间内(例如,不到一分钟)计算出精确的解决方案。

一种方法是使用动态编程,其中状态由下式给出:

A) a 20 bit number m (which will represent which items have been visited so far)
B) a number b in the range 1..20 
C) a number c in the range 1..20

此状态对应于看起来像Start,?,?,?,...,?,b,c的链。 即b和c是最近的2个元素。

数字m是一个位域,表示链中访问了哪些其他元素。换句话说,当且仅当链包括袋中的第i个元素时,m的位i为1。

找到最短链的算法将是:

  1. 设S =由具有开始标记的所有元组组成的状态集。 (所有这些状态将具有相同的链长度2)
  2. 对于从3向上的每个链长y,遍历S中的所有状态并尝试通过使用适当的元组将状态扩展为具有长度y。如果可以,请添加扩展状态以设置S。
  3. 如果位域m最终设置了所有位,则只允许添加带有结束标记的元组。
  4. 如果您设法添加包含结束状态的元组,那么您已找到包含所有元素的最短链。

    对于包中的N个项目,大约有2 ^ N.N.N个状态应该是可管理的。