2

Problem: We have an array of size n and we are am allowed to perform at most K operations where each operation can be

  1. decrease the number of inversions by 1.
  2. make a random shuffle of the whole array.

My problem is to perform the K operations in such a way that the expected number of inversions in the final array are minimized.

Constraints:
100s of testcases with
1 < n < 100
1 < K < n(n-1)/2

My approach: I am thinking about Dynamic programming solution. I can calculate the probabilities of having exactly e inversions in an array of size n using mahonian numbers. I also fill an array dp[k+1][1+n(n-1)/2] row wise such that dp[i][j] denotes the minimal expected inversions in the array having j inversions after i operations have been performed and then using it I can generate the minimal expected value for (i+1)<sup>th</sup> operation for all possible inversions in the array.

The problem with this approach the probabilities are not accurate due to the limitation of doubles in c++ and this algorithm is O(kn<sup>2</sup>) for each test case which is very slow.

For example:
Probability of having no inversion in an array of size 100 = 1.0/factorial(100) ~ 10<sup>-160</sup> (I think there is lack of precision here).

I think that there is some accurate and more efficient approach. Please suggest some Ideas.

Thank you

v78
  • 2,803
  • 21
  • 44
  • 1
    For operation #2, do you mean make a random shuffle of a contiguous subarray, i.e. a subarray of all elements with indices between i and j where 1 <= i < j <= n? Or do you mean a random shuffle of any "subarray" where you can choose any indices you want? Or is it just a random shuffle of the entire array (which does not seem like a very interesting problem, either you shuffle once in the beginning or you don't). – user2566092 Sep 09 '14 at 17:55
  • @user2566092 it is random shuffle of the whole array – v78 Sep 09 '14 at 18:06
  • @userDD Actually I think I was wrong if the array is large and the number of operations is small, then it's probably best to keep randomly shuffling the array until you get a low enough number of inversions just by chance, and then once you do, you finish off by reducing the number of inversions by 1 for the rest of the operations. – user2566092 Sep 09 '14 at 18:13
  • 1
    @user2566092 in the first move we can reduce number of inversions to min(n(n-1)/4,currentInvCount - 1 ), but we cannot anything after k operations. – v78 Sep 09 '14 at 18:17
  • @userDD I agree with your analysis for one operation. But if you have more operations, then you can always choose to shuffle again. Thus, e.g. you could say shuffle first and then if the number of inversions is greater than n(n-1)/4 then shuffle again. This will decrease the final expected number of inversions from n(n-1)/4 to quite a bit less than just subtracting 1 or 2 if n is large, because you have a 3/4 probability of getting lower than expected #inversions when you shuffle, and only 1/4 probability of getting higher than expected #inversions, and the standard deviation grows as n grows. – user2566092 Sep 09 '14 at 18:25
  • @DavidEisenstat That looks like a completely different problem. That one is counting inversions efficiently after deterministic changes. This one is estimating inversions after random operations. – btilly Sep 09 '14 at 18:39
  • 2
    @btilly You're right; it's [this problem](http://www.codechef.com/SEPT14/problems/SEABUB) from the same running September 2014 contest. I'll delete the other comment once this one is visible above the fold. – David Eisenstat Sep 09 '14 at 18:57
  • @user2566092 your approach is good. how will you solve using this , what is complexity etc ?. – v78 Sep 09 '14 at 18:58

1 Answers1

1

In order to answer your question you are going to need to be able to compute the expected #inversions assuming you have k moves left and assuming that at the kth move you shuffle and then you decide to stop shuffling (and then just subtract 1) or continue shuffling depending on how many inversions you get after you shuffle. This is easy if you only have two moves left and the current #inversions is greater than n(n-1)/4. Basically you shuffle first, and then stop shuffling and subtract 1 for your second move if the number of inversions is n(n-1)/4 or lower after you first shuffle, and you shuffle again if the number of inversions is greater than n(n-1)/4 after you first shuffle. For more than 2 moves though, things get more complicated because at the kth move if you shuffle you can choose an upper bound Nk on the number of inversions Nk for which you will stop and just subtract 1 thereafter, and you need to optimize this Nk so that the expected number of inversions is minimal overall. Obviously if k is larger, then Nk should be chosen smaller, but the question is by how much. If you can compute that Nk (for each k), then you will have solved your problem.

My intuition is that you can solve for Nk for all k=1,2,...,K in essentially O(nK) time, using some sort of recursive formulation. I'll update if I work out the details. If true, it would mean that you can solve for the expected number of inversions in essentially O(nK) time as well.

user2566092
  • 4,631
  • 15
  • 20