Pick优化跨越区域的最小元素数

时间:2013-05-21 05:31:17

标签: python algorithm numpy

我有一个优化问题。我从来没有学过算法,只教自己python,所以我不确定这是一个难以解决的难题。该问题的非抽象应用是确定使用可用试剂对DNA进行测序的最便宜方式。现在问题是......

有一个圆形区域,比如0-10,其中10个循环回到0.有长度为1的元素,每个元素跨越区域的一部分,最终目标是在覆盖每个位置时最小化元素的数量。我有许多长度为1的元素,但这些元素并不涵盖整个区域。因此,我需要付费添加其他元素。

因此,最终成本将类似于(元素数量)+ 2(购买的元素数量),目标是最小化成本。这是一个容易解决的问题,还是需要付出巨大努力来解决它?

example data

所以在这个例子中,我会选择在2和5.75处添加一个值,并在大约2.5处删除一些值。

1 个答案:

答案 0 :(得分:2)

我不懂python,但我可以用伪代码帮助你。对于您的约束,这可能不是完全最优,但如果需要,您可以调整它。

让我们假设你的元素有两个属性,beginend,它们分别定义了X坐标,它们分别是开始和结束! (即使你的结尾总是开始+ 1。如果一个元素从9.5开始,考虑它以10.5而不是0.5结束)

将所有元素放入数组elem []中,然后先用较低的begin对它们进行排序。复制第一个元素并将其放在数组的末尾,在10begin坐标上增加end。 (因此它可能会变成类似10.2到11.2的东西)这是为了涵盖问题的循环方面,我们仅将其用于参考,但不计入成本的两倍。

X = 0  (the farthest you have got covered so far)
foreach element i in array, in order, except for last element:
  if elem[i+1].begin <= X
    continue; // this means you dont need the current element, discard it and go to the next iteration of the loop.
  if elem[i].begin <= X
    X = elem[i].end // you will use this element to expand your reach
  else // bad news, you got an empty hole
    add_elements += ceil(elem[i].begin - X)  // ceil = round up to an integer number of elements needed to cover the hole
    X = elem[i].end // you will use this element anyway!

if X < 10 // after the loop ends
  add_elements += ceil(elem[last].begin - X)

你可以重写最后一个if / else只需要一个if,我只是觉得这样会说教更容易理解。

add_elements包含您需要添加的额外元素数量。 ceil()函数是这样的,如果你有一个长度为2.4的连续洞,你知道至少需要3个新元素来修复它。

由于我不知道你需要处理多少元素,因此该算法相当简单快速,O(n logn)的时间复杂度由于初始排序。使用浮点坐标,你不能比这更便宜。

Possibility of improvement: 当您知道有一个洞需要添加要修复的新元素时,可能会在开头和/或结尾丢弃之前拾取的元素一个洞。例如,考虑元素{(0,1),(0.7,1.7),(1.8,2.8),(2,3)}。在第二个和第三个元素之间有一个长度为0.1的孔,但如果你添加一个长度为1的新元素并将其放在1.0和2.0之间,你实际上可以抛弃第二个和第三个元素。