class Solution {
public:
int maxValueOfCoins(vector<vector<int>>& piles, int k) {
// dp[i][k] := max value of picking k coins from piles[i:]
dp.resize(piles.size(), vector<int>(k + 1));
return maxValueOfCoins(piles, 0, k);
}
private:
vector<vector<int>> dp;
int maxValueOfCoins(const vector<vector<int>>& piles, int i, size_t k) {
if (i == piles.size() || k == 0)
return 0;
if (dp[i][k])
return dp[i][k];
int ans =
maxValueOfCoins(piles, i + 1, k); // Pick 0 coins from current pile
int val = 0; // Coins picked from current pile
// Try to pick 1, 2, ..., k coins from current pile
for (int j = 0; j < min(piles[i].size(), k); ++j) {
val += piles[i][j];
ans = max(ans, val + maxValueOfCoins(piles, i + 1, k - j - 1));
}
return dp[i][k] = ans;
}
};