diff --git a/cpp/cherry-pickup-ii.cpp b/cpp/cherry-pickup-ii.cpp new file mode 100644 index 0000000..23de863 --- /dev/null +++ b/cpp/cherry-pickup-ii.cpp @@ -0,0 +1,83 @@ +#include +#include + +namespace { + +using grid_t = std::vector>; + +struct solver { + const int UNDEFINED = -1; + + solver(const grid_t &grid) + : grid(grid), rows(static_cast(grid.size())), + cols(static_cast(grid[0].size())), + dp(rows, std::vector(cols, std::vector(cols, UNDEFINED))) {} + + auto solve() -> int { return solve(0, 0, cols - 1); } + + private: + const grid_t &grid; + int rows, cols; + std::vector dp; + + auto contains(int y, int x) const -> bool { + return y >= 0 && y < rows && x >= 0 && x < cols; + } + + auto solve(int y, int x0, int x1) -> int { + // out of bounds or same + if (!contains(y, x0) || !contains(y, x1) || x0 == x1) { + return 0; + } + + // is memoized + if (dp[y][x0][x1] != UNDEFINED) { + return dp[y][x0][x1]; + } + + auto current = grid[y][x0] + grid[y][x1]; + + // last row + if (y == rows - 1) { + return current; + } + + auto best = 0; + for (int d0 = -1; d0 <= 1; ++d0) { + for (int d1 = -1; d1 <= 1; ++d1) { + best = std::max(best, current + solve(y + 1, x0 + d0, x1 + d1)); + } + } + + dp[y][x0][x1] = best; + return best; + } +}; +} // namespace + +class Solution { + public: + int cherryPickup(const std::vector> &grid) { + return solver(grid).solve(); + } +}; + +int main() { + Solution s; + + assert((s.cherryPickup(std::vector{ + std::vector{3, 1, 1}, + std::vector{2, 5, 1}, + std::vector{1, 5, 5}, + std::vector{2, 1, 1}, + }) == 24)); + assert((s.cherryPickup(std::vector{ + std::vector{1, 0, 0, 0, 0, 0, 1}, + std::vector{2, 0, 0, 0, 0, 3, 0}, + std::vector{2, 0, 9, 0, 0, 0, 0}, + std::vector{0, 3, 0, 5, 4, 0, 0}, + std::vector{1, 0, 2, 3, 0, 0, 6}, + }) == 28)); + + return 0; +}