问题:我们有一个大小为n
的数组,我们可以执行大多数K
次操作,其中每项操作都可以
我的问题是执行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>
(我认为这里缺乏精确度)。
我认为有一些准确而有效的方法。请提出一些想法。
谢谢
答案 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)的时间内解决预期的反转次数。