计算变化数组中的预期反转次数

时间:2014-09-09 17:42:29

标签: c++ algorithm mathematical-optimization inversion expectations

问题:我们有一个大小为n的数组,我们可以执行大多数K次操作,其中每项操作都可以

  1. 将反转次数减少1。
  2. 随机播放整个阵列。
  3. 我的问题是执行K操作,以使最终数组中预期的反转次数最小化。

    约束:
    100个测试用例 1< n< 100
    1< K< N(N-1)/ 2

    我的方法:我在考虑动态编程解决方案。我可以使用mahonian数来计算在大小为e的数组中准确n个反转的概率。我还会逐行填充数组dp[k+1][1+n(n-1)/2],以便dp[i][j]表示在执行j操作后具有i反转的数组中的最小预期反转,然后使用它我可以为数组中所有可能的反转生成(i+1)<sup>th</sup>操作的最小期望值。

    由于c ++中的双精度限制,这种方法的问题不准确,并且对于每个非常慢的测试用例,该算法为O(kn<sup>2</sup>)

    例如
    在大小为100的数组中没有反转的概率= 1.0/factorial(100)10<sup>-160</sup>(我认为这里缺乏精确度)。

    我认为有一些准确而有效的方法。请提出一些想法。

    谢谢

1 个答案:

答案 0 :(得分:1)

为了回答你的问题,你需要能够计算预期的#inversions,假设你有k个左移,并假设在第k个移动你移动然后你决定停止改组(然后只是减去1)或继续改组,取决于你洗牌后获得的倒数。如果你只剩下两个动作并且当前的#inversions大于n(n-1)/ 4,这很容易。基本上你先洗牌,然后停止洗牌,如果第一次洗牌后反转次数为n(n-1)/ 4或更低,则为第二次移动减去1,如果反转次数大于n,则再次洗牌第一次洗牌后(n-1)/ 4。事情变得更加复杂,事情变得更加复杂,因为在第k次移动时如果你洗牌你可以选择你将停止的倒数Nk的上限Nk,然后再减去1,你需要优化这个Nk这样预期的反转次数总体上是最小的。显然,如果k更大,那么Nk应该选择更小,但问题是多少。如果你可以计算出Nk(每个k),那么你就可以解决问题了。

我的直觉是你可以使用某种递归公式,在基本为O(nK)的时间内为所有k = 1,2,...,K求解Nk。如果我弄清楚细节,我会更新。如果为真,则意味着您可以在基本上为O(nK)的时间内解决预期的反转次数。