How to maximize the total probability? - c++

I want to maximize the total probability of winning in a game of random selection which is played as follows,
I have n lottery tickets and out of these n only 1 is the lucky ticket, now I have 2 option either draw a ticket or ask the master to remove some X unlucky ticket out of total tickets, X must be a multiple of k (available) and X must be smaller than total number of tickets.
If i draw an unlucky ticket master will add k unlucky tickets to the pile of tickets.
We have at max m moves to play, each move is one of the following
Either we draw a ticket
Either we ask master to remove X tickets (X is multiple of k)
I want to maximize the probability.
And output the total probability P/Q as P*Q^(-1) where Q is modular inverse of Q.
After observing and playing the game I think the total probability will be maximum only when we play the game in the following way
First move we draw a ticket and probability of winning is 1/n.
If we draw an unlucky ticket in first move k tickets are added and we can ask the master to remove k tickets in second move.
In third move we again draw ticket and probability of winning now is
((n-1)/n)*(1/n) .
Similarly if there are m moves than we can conclude that, total probability of winning is (1-((n-1)/n)^r) where we can find value of r
n
for example :
n = 3 k = 20 m = 3
total probability is 1-(2/3)^2 = 5/9
n = 5 k = 7 m = 1
total probability of winning is = 1/5
Final output :
5*(9)^(-1) % 1000000007 = 555555560
1*(5)^(-1) % 1000000007 = 400000003
If there is other winning strategy in this game please provide it with proof and i don't have a proof for my strategy too so if you can prove my strategy i will be glad to have it as well as a psuedocode will help me to proceed.
we again put the ticket that we picked in the pile again so after drawing wrong we have n+k instead of n+k-1, and also n < k ( for the starting always)
EDIT : Proof of my strategy
for each move we take there are 2 possibilities
either we gain 1/n*(n-1)/n or we gain (n-1)/n*(1/n+k) + (n-1/n)((n+k-1)/n+k)(1/n+2*k)
now after solving both sides we get to equation 1/n left hand side and right hand side is (2*n+3*k-1)/((n+2*k)*(n+k) and i found that R.H.S is always less than or equals to R.H.S
So after further solving i get L.H.S as 2*(k^2) and R.H.S as n^2-n and as given n < k so L.H.S is always greater than R.H.s
Hence proved.
Please provide feedback for the proof.

Your strategy is incorrect. After drawing an unlucky ticket, you would ask the master to remove k tickets, but if you had started playing in exactly the same state, you would have picked a ticket instead. That does not make sense, because the game has no memory of your previous moves, and the present situation should therefore always dictate the best choice.
Let P(n,m,k) be the probability of winning with n tickets, max m moves, and k, with optimal strategy.
If you pick a ticket, then the probability is 1/n + P(n+k-1, m-1, k)*(n-1)/n.
If you don't then the probability is P(n-k, m-1, k)
The optimal choice is the one with best probability, and so:
P(n,m,k) = max( 1/n + P(n+k-1, m-1, k)*(n-1)/n , P(n-k, m-1, k) )
You can could calculate this recursively, with memoization since there are likely to be overlapping subproblems, i.e., with dynamic programming.

Related

How to calculate expected number of turns using DP in O(n)?

A single-player board game. The board is made up of a row of n cells numbered 1 to n from left to
right. Cell ‘j' contains a positive integer cj.
The rules are like this:
You start on the leftmost cell.
On each turn, you roll a fair 6-sided die with A as the outcome number. You
move forward A × cj cells, where j is the index of the cell that you are standing
on.
You win once you exit the board i.e., you win when your index j > n.
For instance, consider the board of size n=10
To begin with, you are at the first cell having the value c1 = 2. In the first turn, you roll a dice
and obtain a value 1, so you move forward 2 cells. Then on the next roll you roll a 5 on cell 3
(with c3 = 4), so you move forward 20 cells makes you exit the board. You win!! You took 2
turns to win.
How to calculate the expected number of turns needed to win using dynamic programming algorithm that runs in time (n) for the above game?
The recurrence relation you're looking for is:
E[j] = 0 (if j > n)
E[j] = 1 + 1/6 * sum_k(E[j + k * c_j]) (otherwise, for k \in 1..6)
For each cell, calculate how many turns to win on average.
For cell[k] with k>=n, this is 0.
For other cells with k<n, it 1 plus the average of turns to win at cell[1..6*c_k].
Cache results and don't recalculate them.
Return turns to win from cell 0.
Yes, this is seemingly nothing non-obvious. Dynamic programming is seeming to do nothing non-obvious, with an appropriately bounded cache in the middle of the naive algorithm.
The trick is arranging the problem to have a cache with good bounds that makes a naive algorithm collapse into not doing much work.

What is the best approach to dp for question TRT (treat for cows) of spoj?

FJ has purchased N (1 <= N <= 2000) yummy treats for the cows who get money for giving vast amounts of milk. FJ sells one treat per day and wants to maximize the money he receives over a given period time. The treats are interesting for many reasons:
The treats are numbered 1..N and stored sequentially in single file in a long box that is open at both ends. On any day, FJ can retrieve one treat from either end of his stash of treats.
Like fine wines and delicious cheeses, the treats improve with age and command greater prices.
The treats are not uniform: some are better and have higher intrinsic value. Treat i has value v(i) (1 <= v(i) <= 1000).
Cows pay more for treats that have aged longer: a cow will pay v(i)*a for a treat of age a.
Given the values v(i) of each of the treats lined up in order of the index i in their box, what is the greatest value FJ can receive for them if he orders their sale optimally?
The first treat is sold on day 1 and has age a=1. Each subsequent day increases the age by 1.
Input
Line 1: A single integer, N
Lines 2..N+1: Line i+1 contains the value of treat v(i)
Output
The maximum revenue FJ can achieve by selling the treats
Example
Input:
5
1
3
1
5
2
Output:
43
What is the basic approach to dp in this problem and how do i process age in dp matrix...? Only approach hitting on my mind is the recursive one... i'm new to DP and i've done some basic dp problems but this is outta my mind... this is what i tried so far
int give(int a[],int x,int y,int age)
{
if(x==y) return age*a[x];
return max(age*a[x]+give(a,x+1,y,age+1),age*a[y]+give(a,x,y-1,age+1));
}
x=starting index ,initialized from 0, y=last index , n-1, age=1 at first call
The first thing to observe is that the current state doesn't depend on the history of where we were taking the treats from. The only thing we care about is how many times we took the treat from the left and how many times we took it from the right.
Therefore the state can be encoded with just 2 numbers: left offset and right offset.
Let f(i,j) be the amount of money we can still get if we until the current move sold. We know that there we have already taken i+j objects from the line, so the age is also i+j.
Therefore we just have to check which position we want to take from, and pick the better one. Well if we pick a treat from the left our amount gained will be
cost * time + f( i + 1 , j ) = cost * (i + j) + f( i + 1 , j ).
The amount if we take from the right has a very similar formula
cost_right * (i + j) + f( i , j + 1 ).
Therefore we can knowing f(i+1,j) and f(i,j+1) compute f(i,j).
Well this can be done using dynamic programming by storing a 2D array of size n*n that stores either -1 if f(i,j) is unknown, or the value of f(x,y) if it is known. Then you can simply update the recursive method described above to actually store the results and return the solution if it is already known. If we take a look at your code example we can modify it to run in time.
int give(int a[],int x,int y,int age)
{
if(dp[x][y]!=-1) return dp[x][y];
if(x==y) return age*a[x];
int answer=max(age*a[x]+give(a,x+1,y,age+1),age*a[y]+give(a,x,y-1,age+1));
dp[x][y]=answer;
return answer;
}
This is just a snippet, as you'll need to fix the boundary conditions and make the actual global dp array, but I hope it is enough to get started.

Number of ways to pick at least x balls (balls are identical)?

There are N distinct boxes of balls in total. There are P boxes each containing A number of balls and remaining Q boxes contains B number of balls each.
Given a number X, what are the total the number of ways in which you can pick at least X balls from the boxes.
P+Q = N
Example: Number of P boxes=2 which contain 2 balls each, Number of Q boxes=1 which contain 2 balls. X=3(Given) where x=minimum number of balls to be picked
So, P+Q=3 (total number of boxes)
Combinations for the number of ways to pick atleast x i.e. 3 balls would be:
combinations of 3:(111),(210),(120),(021),(012),(201),(102)
combinations of 4:(220)(202)(022)(211)(121)(112)
combinations of 5:(212)(122)(221)
combinations of 6: (222)
total Combinations: 17
My Approach:
I have used "Stars and Bars Approach":
To calculate combinations of 6: x+y+z=6 which is converted into (2-x)+(2-y)+(2-z)=6 giving out x+y+z=0.
So, the combination of 6 becomes Binomial(2C2)=1
Similarly, Combinations of 5 becomes Binomial(3C2)=3
Combinations of 4= Binomial(4C2)=6
Combinations of 3= Binomial(5C2)=10
1+3+6+10=20
but the answer should be 1+3+6+7=17
Edge case has appeared on calculating the combinations of 3. How should I tackle this problem?
EDIT: CODE ADDED in python
global total_combinations
total_combinations=0
from math import factorial
def combinations(a):
global total_combinations
bars=numberofAs+numberofBs-1
stars=a
total_combinations+=factorial(stars+bars)/(factorial(bars)*factorial(stars))
numberofAs,numberofBs,numberofballsinA,numberofballsinB=map(int,raw_input().split())
x=int(raw_input())
operational_array=[]
for i in range(numberofAs):
operational_array.append(numberofballsinA)
for i in range(numberofBs):
operational_array.append(numberofballsinB)
max_x=sum(operational_array) #calculate combinations from x to max_x
k=max_x
for i in range(max_x,x-1,-1):
k=max_x-i
combinations(k)
print total_combinations
The number of balls you can take out of a box containing A balls is the number of balls you can put into an empty box of capacity A.
There are known formulas for that problem.
If all boxes have the same number of balls initially (as in the given example, in which A=B=2),
and that number is equal to or greater than the total number of balls to be removed from the boxes, then "stars and bars" will work.
But if the number of balls to be removed is greater than the number in a single box, there is an iterative formula to find the number of ways the balls can be selected.
To remove t balls from k boxes containing m balls each,
from scipy.special import comb
def combinations_with_limit(t, k, m):
total = 0
max_full_boxes = min(k, int(t/(m + 1)))
for i in range(max_full_boxes + 1):
total += int((-1)**i) * comb(k, i, exact=True) * comb(t + k - 1 - i*(m + 1), k - 1, exact=True)
return total
This is based on the formula in this math.stackexchange answer, but using t rather than n for the total number of balls removed in order to avoid confusion with the use of N in this question.
You can optimize and improve the style of this code, of course
(for example, I wouldn't suggest writing int((-1)**i) in production code);
the reason it's written this way is to stay as close as practical to the format of the MSE answer.
Not surprisingly, we have to think a little harder in the case where A and B are different.
To remove a total of t balls from p boxes containing a balls each and q boxes containing b balls each,
def combinations_with_two_limits(t, p, q, a, b):
total = 0
min_balls_from_p = max(0, t - q*b)
max_balls_from_p = min(t, p*a)
for i in range(min_balls_from_p, max_balls_from_p + 1):
total += combinations_with_limit(i, p, a) * combinations_with_limit(t - i, q, b)
return total
The idea here is that you first decide how to allocate the t balls into two groups, one to be removed from the boxes containing a balls and the other to be removed from the boxes containing b balls,
and then count all the ways you can select those subsets of the balls from those subsets of the boxes.
It may be possible to optimize the code further by going back to the derivation of the MSE formula cited above (either through generating functions or the inclusion-exclusion principle), but I wouldn't try it unless it's really critical to shave a few percentage points off the running time.
To remove at least X balls from the boxes, take the sum of the values of
combinations_with_two_limits as t takes on all integer values from X up to and including the largest number of balls you can remove
(which is P*A + Q*B).
Break it in 2 parts where you pick k balls from the P boxes of capacity A and x-k balls from the Q bins with capacity B. Use stars and bars approach on each side to calculate the number of ways to pick k,x-k respectively, and multiply to get the total. (Considering of course that you can only do that when both k,x-k do not exceed the capacities A,B).
To not consider the cases where k>A and x-k>B you have to implement the formula below
Which counts all combinations in which n items are allocated to k bins, excluding combinations where at least one bin contains more than C items.
In your case you need to use this formula twice, once to allocate k balls to P bins with capacity A, and once to allocate x-k balls to Q bins with capacity B.
Then the multiplication should give you the correct result.

2 player team knowing maximum moves

Given a list of N players who are to play a 2 player game. Each of them are either well versed in making a particular move or they are not. Find out the maximum number of moves a 2-player team can know.
And also find out how many teams can know that maximum number of moves?
Example Let we have 4 players and 5 moves with ith player is versed in jth move if a[i][j] is 1 otherwise it is 0.
10101
11100
11010
00101
Here maximum number of moves a 2-player team can know is 5 and their are two teams that can know that maximum number of moves.
Explanation : (1, 3) and (3, 4) know all the 5 moves. So the maximal moves a 2-player team knows is 5, and only 2 teams can acheive this.
My approach : For each pair of players i check if any of the players is versed in ith move or not and for each player maintain the maximum pairs he can make with other players with his local maximum move combination.
vector<int> pairmemo;
for(int i=0;i<n;i++){
int mymax=INT_MIN;
int countpairs=0;
for(int j=i+1;j<n;j++){
int count=0;
for(int k=0;k<m;k++){
if(arr[i][k]==1 || arr[j][k]==1)
{
count++;
}
}
if(mymax<count){
mymax=count;
countpairs=0;
}
if(mymax==count){
countpairs++;
}
}
pairmemo.push_back(countpairs);
maxmemo.push_back(mymax);
}
Overall maximum of all N players is answer and count is corresponding sum of the pairs being calculated.
for(int i=0;i<n;i++){
if(maxi<maxmemo[i])
maxi=maxmemo[i];
}
int countmaxi=0;
for(int i=0;i<n;i++){
if(maxmemo[i]==maxi){
countmaxi+=pairmemo[i];
}
}
cout<<maxi<<"\n";
cout<<countmaxi<<"\n";
Time complexity : O((N^2)*M)
Code :
How can i improve it?
Constraints : N<= 3000 and M<=1000
If you represent each set of moves by a very large integer, the problem boils down to finding pair of players (I, J) which have maximum number of bits set in MovesI OR MovesJ.
So, you can use bit-packing and compress all the information on moves in Long integer array. It would take 16 unsigned long integers to store according to the constraints. So, for each pair of players you OR the corresponding arrays and count number of ones. This would take O(N^2 * 16) which would run pretty fast given the constraints.
Example:
Lets say given matrix is
11010
00011
and you used 4-bit integer for packing it.
It would look like:
1101-0000
0001-1000
that is,
13,0
1,8
After OR the moves array for 2 player team becomes 13,8, now count the bits which are one. You have to optimize the counting of bits also, for that read the accepted answer here, otherwise the factor M would appear in complexity. Just maintain one count variable and one maxNumberOfBitsSet variable as you process the pairs.
What Ill do is:
1. Do logical OR between all the possible pairs - O(N^2) and store it's SUM in a 2D array with the symmetric diagonal ignored. (thats we save half of the calc - see example)
2. find the max value in the 2D Array (can be done while doing task 1) -> O(1)
3. count how many cells in the 2D array equals to the maximum value in task 2 O(N^2)
sum: 2*O(N^2)+ O(1) => O(N^2)
Example (using the data in the question (with letters indexes):
A[10101] B[11100] C[11010] D[00101]
Task 1:
[A|B] = 11101 = SUM(4)
[A|C] = 11111 = SUM(5)
[A|D] = 10101 = SUM(3)
[B|C] = 11110 = SUM(4)
[B|D] = 11101 = SUM(4)
[C|D] = 11111 = SUM(5)
Task 2 (Done while is done 1):
Max = 5
Task 3:
Count = 2
By the way, O(N^2) is the minimum possible since you HAVE to check all the possible pairs.
Since you have to find all solutions, unless you find a way to find a count without actually finding the solutions themselves, you have to actually look at or eliminate all possible solutions. So the worst case will always be O(N^2*M), which I'll call O(n^3) as long as N and M are both big and similar size.
However, you can hope for much better performance on the average case by pruning.
Don't check every case. Find ways to eliminate combinations without checking them.
I would sum and store the total number of moves known to each player, and sort the array rows by that value. That should provide an easy check for exiting the loop early. Sorting at O(n log n) should be basically free in an O(n^3) algorithm.
Use Priyank's basic idea, except with bitsets, since you obviously can't use a fixed integer type with 3000 bits.
You may benefit from making a second array of bitsets for the columns, and use that as a mask for pruning players.

To make an array non-decreasing using dynamic programing

I came accross this question in a programming contest, i think it can be solved by DP but cannot think of any, so plz help. Here's the questn :
There are n stack of coins placed linearly, each labelled from 1 to n. You also have a sack of coins containing infinite coins with you. All the coins in the stacks and the sack are identical. All you have to do is to make the heights of coins non-decreasing.
You select two stacks i and j and place one coin on each of the stacks of coins from stack'i' to stack'j' (inclusive). This complete operations is considered as one move. You have to minimize the number of moves to make the heights non-decreasing.
No. of Test Cases < 50
1 <= n <= 10^5
0 <= hi <= 10^9
Input Specification :
There will be a number of test cases. Read till EOF. First line of each test case will contain a single integer n, second line contains n heights (h[i]) of stacks.
Output Specification :
Output single integer denoting the number of moves for each test case.
for eg: H={3,2,1}
answer is 2
step1: i=2, j=3, H = {3,3,2}
step2: i=3, j=3, H = {3,3,3}