SPOJ问题集(经典):9386。重新安排II#[MAIN112]

时间:2011-09-01 20:44:43

标签: algorithm sorting permutation

问题描述 (为方便起见,此处引用):

  

对于N个整数的序列,A1,A2,..... AN

     

我们可以计算稳定性因子P,如

     

P =所有的总和(abs(Ai-Ai-1)* C [i])其中2 <= i <= N

     

C [i]是将数字放在第i位的成本

     

您的任务是找到给定N个数的最小P值   所有不同的排列。


我只需要朝着正确的方向努力,关于解决这个问题的一般方法。 (一点点伪代码是受欢迎的,但是一旦整体算法通常很清楚,我有信心为解决方案编写代码)

我已经考虑了这个问题很长一段时间了,但仍然坚持到达任何满足此问题约束的解决方案(N <= 15)蛮力方法似乎只能达到N = 10真的。


首先,对于最大可能的测试案例N = 15,我不相信你能够枚举并考虑所有15个!排列以便在足够好的时间内找到答案,因为复杂性类不允许这样做。

因此,我们需要做出几个简化的假设来减少这个搜索空间。这就是我被困住的地方。或者它可能只是一种更聪明的方式来开始遍历这个排列空间?

我尝试使用动态编程来解决这个问题,因为排列共享许多常见位,可以预先计算(记忆)并在必要时存储和重用,例如。 A [] = 123456&amp; A [] = 123465都会为1234-提供相同的部分金额,但这并没有成功,因为你仍然必须通过15!排列并且在此之前将采用TLE方式,所以这没有用。

另一个想法是使用连续A和C []的所有元素之间差异的所有可能排列,并首先找到将产生最小abs(A [i] -A [j])*的对所有这些中的C [k]值,分配那些&amp;将它们标记为已使用,然后继续使用i或j之一形成下一对,再次迭代并重复。这应该在多项式时间内完成(n ^ 3约。我在猜测),但是假设在一些例子中失败了。

我不认为这个问题应该如此难以将其转化为某种图形问题 - 其中A [i],A [j]形成节点,而C [k]是边缘链接的成本这些节点,或者可能是一些布尔SAT问题...所有这些似乎完全都是在错误的轨道上。

如果您要谷歌这一点,除了托管此问题的SPOJ网站之外,您可能几乎找不到与此问题相关的任何内容。

非常感谢提前。

1 个答案:

答案 0 :(得分:1)

你可以在子集上使用O(n * 2 ^ n)空间,O(n ^ 2 * n ^ 2)时间动态规划算法来解决它。

关键的洞察力是,当您从左到右构建最佳解决方案时,只有先前放置的数字和使用的子集很重要,而不是事物被放置在使用的子集中的顺序。

计算与Travelling Salesman Problem.

的解决方案基本相同

你的DP想法是正确的。洞察力只是在所有这些部分路径之后的最佳路径是相同的

1235

1325

2135

2315

3125

3215

所以你实际上并不需要探索所有可能的排列,只有那些具有最佳部分路径的排列。

这是一些实现所述算法的TLE Python代码,但由于Python中的常数因子减速而失败。我转换为C ++并获得了AC。

global A
global C

A = []
C = []

def Solve(used, last, cache):
  if (used, last) in cache:
      return cache[(used, last)]
  cur_pos = len(used)
  if cur_pos == len(A):
    return 0

  mn = 1e10
  for idx in range(len(A)):
      if not idx in used:
          next_used = used.union([idx])
          subcost = Solve(next_used, A[idx], cache)
          additional = C[cur_pos] * abs(last - A[idx])
          mn = min(mn, subcost + additional)
  cache[(used, last)] = mn
  return mn

T = int(raw_input())
for i in range(T):
  N = int(raw_input())
  A = map(int, raw_input().split())
  C = map(int, raw_input().split())
  cache = {}
  print min(Solve(frozenset([idx]), A[idx], cache) for idx in range(len(A)))