1

我正在用 C# 4.0 编写一个程序,我将其抽象为以下内容(我提到了该语言,以便您知道我必须使用哪些库;没有第三方库):


S = { s1, s2, s3, ..., sn }.

对于所有si,sjS, i != j, 函数f(si, sj)是 的一个元素{ true, false }。调用这个函数f非常昂贵,但是应该尽可能少地调用。

给定集合T = { t1, t2, t3, ..., tm }的一个非空子集S,计算一个序列,该序列U = u1, u2, u3, ..., uo包含 的所有元素Tf(ui, uj) == false对于 all i < jf(ui, s') == false对于 allis'in S - U。您可以假设存在这样的序列。


虽然这与学校无关(这是为了工作),但我更希望得到最少的帮助,让我找到你能想到的最佳解决方案,这样我就可以了解更多:)


提示(一些我想过的东西:)

  1. 您需要至少访问每个节点一次。在and中 考虑T = { t }andf(t, s') == false的情况。在这种情况下,一次也足够了。s'S - T|S| >= 2

  2. 最少U必须计算。这种计算可以用以下形式表示: 一个|S|x|S|邻接矩阵,其条目为

    • ?: 我不知道
    • 1: 取决于。
    • 0: 不依赖。
    • -: 我不在乎。

考虑一下这一点(我正在通过一个示例来查看是否存在最佳潜在检查序列的模式以帮助开发算法)。 S = { a, b, c, d, e } T = { a, b, c }(由星星表示):

     a  b  c  d  e
   ----------------
*a | -  -  -  ?  ?
*b | -  -  -  ?  ?
*c | -  -  -  ?  ?
 d | -  -  -  -  ?
 e | -  -  -  ?  -

U = { a, b, c }最初。对角线是-因为f在其操作数相等时未定义。由于a和已经在集合中,b因此c是否有人依赖它们并不重要,因此-.

f(a, d)由于对称性,f(a, e), , f(b, d), f(b, e), f(c, d),f(c, e)都是平等的候选者。假设我们选择f(a, d)它返回 false。我们的表格现在看起来像这样:

     a  b  c  d  e
   ----------------
*a | -  -  -  0  ?
*b | -  -  -  ?  ?
*c | -  -  -  ?  ?
 d | -  -  -  -  ?
 e | -  -  -  ?  -

情况1:U = { a, b, c }

要找出这一点,我们可以通过 3 次检查来做到这一点,如果幸运的话,检查f(b, d), f(c, d)并且f(e, d)让它们都成为false

案例二:U = { a, b, c, d, e }

要找出这一点,我们可以通过 2 次检查来完成,如果幸运的话,检查f(b, d)f(a, e)让它们都返回true

(我还没有完全想好这些,我要去吃饭了。感谢大家阅读!)

案例3:U = { a, b, c, d }

案例4:U = { a, b, c, e }

4

1 回答 1

-1

我的理解是,您希望从子集 T 中的任何节点开始可以访问的所有节点...如果这是您的意思,您可以试试这个...

  1. 用所有节点填充字典(将节点作为键,将访问的布尔值作为值(将此值作为假开始))
  2. 用子集 T 中的节点填充队列(添加它们时在字典中搜索它们并将它们标记为已访问)
  3. 选择队列中的第一个元素检查您可以从中访问的节点,在字典中搜索是否已访问,如果已访问则跳过,如果没有,将它们添加到队列并将它们设置为已访问,删除队列的第一个元素
  4. 重复 3 直到队列中没有项目

您可以从 t 开始访问的节点子集是您在字典中标记的节点

希望能帮助到你...

于 2012-08-16T19:51:43.383 回答