Recursion->Top Down-> Bottom Up || Easy to understand code
RECURSION, TLE\n\nclass Solution {\npublic:\n    //startPileIdx is always 0\n    //piles under consideration for each call ==> [pileIdx = 0 to pileIdx = endPile
### RECURSION, TLE\n```\nclass Solution {\npublic:\n    //startPileIdx is always 0\n    //piles under consideration for each call ==> [pileIdx = 0 to pileIdx = endPileIdx]\n    int solve(vector<vector<int>>&piles, int endPileIdx, int k)\n    {\n        if (endPileIdx < 0 || k == 0) return 0;\n        \n        int currPileSize = piles[endPileIdx].size(); \n        int maxCanPick = min(k, currPileSize);\n        \n        //consider \'not picking\' any coin\n        int maxSum = solve(piles, endPileIdx - 1, k);  //DON\'T PICK ANY COIN FROM CURR PILE\n        int pickedSum = 0;\n        //===============================================================================\n        //now consider picking some coins\n        for (int i = 0; i < maxCanPick; i++)\n        {\n            int coinValue = piles[endPileIdx][i];\n            pickedSum += coinValue;\n            \n            int nextMaxSum = solve(piles, endPileIdx - 1, k - i - 1); \n            maxSum = max(maxSum, pickedSum + nextMaxSum);\n        }\n        //=================================================================================\n        return maxSum;\n        \n    }\n    int maxValueOfCoins(vector<vector<int>>& piles, int k) \n    {\n        int n = piles.size();\n        int ans = solve(piles, n - 1, k);\n        return ans;\n        \n    }\n};\n```\n//====================================================================================================================\n\n### TOP DOWN [Memoization], Accepted\n```\nclass Solution {\npublic:\n    //startPileIdx is always 0\n    //piles under consideration for each call ==> [pileIdx = 0 to pileIdx = endPileIdx]\n    int solve(vector<vector<int>>&piles, vector<vector<int>>&dp, int endPileIdx, int k)\n    {\n        if (endPileIdx < 0 || k == 0) return 0;\n        if (dp[endPileIdx][k] != -1) return dp[endPileIdx][k];\n        \n        int currPileSize = piles[endPileIdx].size(); \n        int maxCanPick = min(k, currPileSize);\n        \n        //consider \'not picking\' any coin\n        int maxSum = solve(piles, dp, endPileIdx - 1, k);  //DON\'T PICK ANY COIN FROM CURR PILE\n        int pickedSum = 0;\n        //===============================================================================\n        //now consider picking some coins\n        for (int i = 0; i < maxCanPick; i++)\n        {\n            int coinValue = piles[endPileIdx][i];\n            pickedSum += coinValue;\n            \n            int nextMaxSum = solve(piles, dp, endPileIdx - 1, k - i - 1); \n            maxSum = max(maxSum, pickedSum + nextMaxSum);\n        }\n        //=================================================================================\n        return dp[endPileIdx][k] = maxSum;\n        \n    }\n    int maxValueOfCoins(vector<vector<int>>& piles, int k) \n    {\n        int n = piles.size();\n        vector<vector<int>>dp(n, vector<int>(k + 1, -1));\n        int ans = solve(piles, dp, n - 1, k);\n        return ans;\n    }\n};\n```\n//================================================================================================================================\n\n### BOTTOM UP, Accepted\n\n```\nclass Solution {\npublic:\n    int maxValueOfCoins(vector<vector<int>>& piles, int k) \n    {\n        int n = piles.size();\n        vector<vector<int>>dp(n, vector<int>(k + 1, 0)); \n        //for considering [number of piles = n]\n        //we must already have answers for [number of piles = (n - 1)]\n        //thus we need to go bottom up\n        //we need to go from [no. of piles under consideration = 1 to n]\n        \n        //consider only (endPileIdx + 1) number of piles at a time\n        for (int endPileIdx = 0; endPileIdx < n; endPileIdx++) //count of piles = endPileIdx + 1\n        {\n            int currPileSize = piles[endPileIdx].size();\n            for (int coinsToPick = 1; coinsToPick <= k; coinsToPick++)\n            {\n                //=============================================================================\n                //DON\'T PICK ANY COIN FROM CURR PILE\n                int maxSum = (endPileIdx - 1 < 0)? 0 : dp[endPileIdx - 1][coinsToPick];  \n                \n                int maxCanPick = min(coinsToPick, currPileSize);\n                int pickedSum = 0;\n                //now consider picking some coins\n                for (int i = 0; i < maxCanPick; i++)\n                {\n                    int coinValue = piles[endPileIdx][i];\n                    pickedSum += coinValue;\n                    \n                    int nextMaxSum = 0;\n                    if (endPileIdx > 0) \n                        nextMaxSum = dp[endPileIdx - 1][coinsToPick - i - 1];\n                    maxSum = max(maxSum, pickedSum + nextMaxSum);\n                }\n                //=======================================================================================\n                dp[endPileIdx][coinsToPick] = maxSum;\n            }\n        }\n        return dp[n - 1][k];\n    }\n};\n````\n\n
['Dynamic Programming', 'C', 'C++']