Maximum Value of K Coins From Piles - Bottom-up DP explained
Problem Statement:
There are n
piles of coins on a table. Each pile consists of a positive number of coins of assorted denominations.
In one move, you can choose any coin on top of any pile, remove it, and add it to your wallet.
Given a list piles
, where piles[i]
is a list of integers denoting the composition of the ith
pile from top to bottom, and a positive integer k
, return the maximum total value of coins you can have in your wallet if you choose exactly k
coins optimally.
Example 1:
Input: piles = [[1,100,3],[7,8,9]], k = 2 Output: 101 Explanation: The above diagram shows the different ways we can choose k coins. The maximum total we can obtain is 101.
Example 2:
Input: piles = [[100],[100],[100],[100],[100],[100],[1,1,1,1,1,1,700]], k = 7 Output: 706 Explanation: The maximum total can be obtained if we choose all coins from the last pile.
Constraints:
n == piles.length
1 <= n <= 1000
1 <= piles[i][j] <= 105
1 <= k <= sum(piles[i].length) <= 2000
Solution:
We define dp[i][j]
as the the answer considering 1st i
piles for at most j
coins. Hence final answer is dp[n][k]
. In base case we consider i=0
ie considering zero piles. This row will be just zeroes. Similarly for j=0
column also, it will be all zeroes.
Consider any general dp[i][j]
.
We can take 0 coins from i
th pile and all the j
coins from the first i-1
piles. The value for this situation is dp[i-1][j] + 0
.
We can also take 3 coins from ith pile
(assume valid) and j-3
coins from the first i-1
piles. The value for this situation is dp[i-1][j-3] + piles[i-1][0]+piles[i-1][1]+piles[i-1][2]
.
Similarly we can have other possiblities as well. dp[i][j]
is the maximum of all these possibilities.
We define cur
as the number of coins we take from the current pile and curSum
as the sum of values of these cur
coins.
int maxValueOfCoins(vector<vector<int>>& piles, int k)
{
int n = piles.size();
vector<vector<int>> dp(n+1, vector<int>(k+1, 0));
for (int i=1; i<=n; i++)
{
for (int j=0; j<=k; j++)
{
dp[i][j] = dp[i-1][j]; // cur=0
int curSum = 0;
for (int cur=1; cur<=min((int)piles[i-1].size(),j); cur++)
{
curSum += piles[i-1][cur-1];
dp[i][j] = max(dp[i][j], dp[i-1][j-cur]+curSum);
}
}
}
return dp[n][k];
}
\(TC= O(n\sum_{i=1}^n {P_i})\) where $P_i$ is the size of ith pile. \(SC: O(nk)\)