C++ 变化阵列中期望反转数的计算

C++ 变化阵列中期望反转数的计算,c++,algorithm,mathematical-optimization,inversion,expectations,C++,Algorithm,Mathematical Optimization,Inversion,Expectations,问题:我们有一个大小为n的数组,我们最多可以执行K个操作,每个操作都可以执行 将反转次数减少1 对整个阵列进行随机洗牌 我的问题是执行K操作时,要使最终数组中的预期反转数最小化 约束条件: 具有 1

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

  • 将反转次数减少1
  • 对整个阵列进行随机洗牌
  • 我的问题是执行
    K
    操作时,要使最终数组中的预期反转数最小化

    约束条件:
    具有
    1 1 我的方法:我正在考虑动态规划解决方案。我可以使用马龙数计算在一个大小为
    n
    的数组中精确地进行
    e
    反转的概率。我还按行填充数组
    dp[k+1][1+n(n-1)/2]
    ,这样
    dp[I][j]
    表示在执行
    I
    操作后,数组中具有
    j
    反转的最小预期反转,然后使用它我可以生成
    (I+1)的最小预期值对阵列中所有可能的反转进行th
    操作

    该方法的问题是由于C++中的双倍限制而导致的概率不准确,并且对于每一个测试用例来说,该算法都是<代码> O(KN2)< /代码>。p> 例如:
    在大小为100的数组中没有反转的概率=
    1.0/阶乘(100)
    ~
    10-160
    (我认为这里缺少精度)

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


    谢谢

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


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

    对于运算#2,您的意思是对连续子阵列进行随机洗牌,即索引在i和j之间的所有元素的子数组,其中1@user2566092是整个元素的随机洗牌array@userDD实际上,我认为我错了,如果数组很大,操作数很小,那么最好继续随机洗牌数组,直到碰巧得到足够少的反转数,一旦您这样做了,您就可以在剩下的操作中将反转数减少1来结束。@user2566092在第一步中,我们可以将反转数减少到min(n(n-1)/4,currentInvCount-1),但在k次操作之后,我们不能做任何事情。@b您说得对;来自2014年9月的同一场跑步比赛。我会删除其他评论,一旦这一条在折叠上方可见。