Maximum profit-memory, DP, optimality
I was tinkering with the problem in algorithm games, I tried the following problem but couldn't find an efficient way to do it ::
So please help me. This is problem.
This is the exact link :: http://community.topcoder.com/tc?module=Static&d1=match_editorials&d2=srm228
I assume you would like to solve this problem yourself, so I will give you a hint: this problem has an optimal substructure .
Imagine you have both coin solutions N-1
(no leftmost and no rightmost). It would be easy to compute the solution for the moments N
, then?
You can use two related methods to use this property - dynamic programming and its subtype called memoization . The idea is to keep the solution to each subproblem with L
coins missing on the left and R
coins missing on the right (use an array for that NxN
). Before solving the problem, check the array to make sure you've already solved it. You will need to solve no more than N^2/2
subproblems to find a solution.
Here's the pseudocode for a memoized solution:
// solved[L][R] array contains the highest value a player could get
// on a subproblem where L coins are missing from the left
// and R are missing from the right of the original sequence on his move
int solved[N][N] // initialize each element to -1.
int coins[N] // initialize with coin values
int solve(int L, int R) {
if (L+R == N) return 0; // No coins remain
if (solved[L][R] >= 0) return solved[L][R];
int remaining = sum(coins from L to R)
int takeLeft = remaining - solve(L+1, R);
int takeRight = remaining - solve(L, R+1);
int result = max(takeLeft, takeRight);
solved[L][R] = result;
return result;
}
main() {
int alice = solve(0, 0);
int bob = sum(coins) - alice;
}
I remember TopCoder running this issue for a while in early 2005 or 2006, but I don't remember enough details to find their problem archive.
source to share
You can solve it with dynamic programming . The state can be represented:
set of available coins,
whos turn it is
For each state, you must calculate the maximum amount of money that the person in turn can win.
Council. The rules of this game can be described set of available coins
as an interval.
@edit
for(int interval_size = 1; interval_size <= n; interval_size++) {
for(int interval_start = 0; interval_start + interval_size <= n; interval_start++) {
// result[interval_start][interval_start + interval_size] depends only on
// -> result[interval_start][interval_start + interval_size - 1]
// -> result[interval_start + 1][interval_start + interval_size]
}
}
source to share
Let dp[i, j] = maximum profit alice can make for the coints i, ... j
.
We have:
dp[i, i] = input[i] for all 1 <= i <= N
dp[i, i + 1] = max(input[i], input[i + 1])
dp[i, j] = max(// take first coin, opponent will minimize your next move
input[i] + min(dp[i + 2, j], dp[i + 1, j - 1]),
// take last coin, opponent will still minimize your next move
input[j] + min(dp[i, j - 2], dp[i - 1, j - 1]))
source to share
//@ IVlad ::Implement your code ,its giving incorrect answer.Had I implemented it properly??
int coins[1000];
int dp[1000][1000];
int main()
{
int T,N;//N=How many coins are there
cin>>T; //No of Test Cases.
while(T--)
{
cin>>N;
for(int i=1;i<=N;++i)
{
cin>>coins[i];
}
for(int i=1;i<=N;++i)
{
dp[i][i]=coins[i];
}
for(int i=1;i<=N;++i)
{
if(i+1<=N)
dp[i][i + 1] = max(coins[i], coins[i + 1]);
}
for(int i=1;i<=N;++i)
{
for(int j=1;j<=N;++j)
{
if((i+2)<=N && (i+1)<=N && (j-2)>=1 && (i-1)>=1 && (j-1)>=1)
dp[i][j]=max( (coins[i] + min(dp[i + 2] [j], dp[i + 1][ j - 1])),coins[j] + min(dp[i] [j - 2], dp[i - 1] [j - 1]));
}
}
cout<<dp[1][N]<<endl;//Answer
}
return 0;
}