diff --git a/638. Shopping Offers.cpp b/638. Shopping Offers.cpp new file mode 100644 index 0000000..1610892 --- /dev/null +++ b/638. Shopping Offers.cpp @@ -0,0 +1,98 @@ +/* + * Shopping Offers (DFS + Memoization) + * + * Description: + * In LeetCode Store, there are n items to buy. Each has a normal price. + * Some special bundle offers let you buy multiple items together at a discount. + * You want to get all items in your "needs" list at the lowest total cost. + * + * Approach: + * - Use recursion (DFS) to try all ways of buying: + * 1. Buy items one-by-one at regular prices. + * 2. Try each special offer (if it doesn't exceed the needs). + * - Memoize the result for each unique "needs" state to avoid recomputation. + * + * Steps: + * 1. Define a helper function dfs(currentNeeds) → minimum cost for these needs. + * 2. Base cost = sum(need[i] * price[i]). + * 3. For each special offer: + * - Check if we can apply it (doesn't exceed needs). + * - If yes, subtract items and call dfs() recursively. + * 4. Memoize and return the minimum cost found. + * + * Time Complexity: O(n * product(needs[i])) (worst case) + * Space Complexity: O(product(needs[i])) (for memoization) + */ + +#include +using namespace std; + +class Solution { +public: + unordered_map memo; // memoization cache + + // Convert current needs to a string key for memo + string encode(vector& needs) { + string key; + for (int num : needs) key += to_string(num) + ","; + return key; + } + + // Recursive function to find the minimum cost + int dfs(vector& price, vector>& special, vector needs) { + string key = encode(needs); + if (memo.count(key)) return memo[key]; + + int n = price.size(); + int cost = 0; + + // Base case: buy all items individually + for (int i = 0; i < n; i++) { + cost += needs[i] * price[i]; + } + + // Try applying each special offer + for (auto& offer : special) { + vector newNeeds = needs; + bool valid = true; + + for (int i = 0; i < n; i++) { + newNeeds[i] -= offer[i]; + if (newNeeds[i] < 0) { // can't buy more than needed + valid = false; + break; + } + } + + if (valid) { + cost = min(cost, offer[n] + dfs(price, special, newNeeds)); + } + } + + memo[key] = cost; + return cost; + } + + int shoppingOffers(vector& price, vector>& special, vector& needs) { + memo.clear(); + return dfs(price, special, needs); + } +}; + +int main() { + Solution sol; + + // Test Case 1 + vector price1 = {2, 5}; + vector> special1 = {{3, 0, 5}, {1, 2, 10}}; + vector needs1 = {3, 2}; + cout << "Test Case 1: " << sol.shoppingOffers(price1, special1, needs1) << endl; // 14 + + // Test Case 2 + vector price2 = {2, 3, 4}; + vector> special2 = {{1, 1, 0, 4}, {2, 2, 1, 9}}; + vector needs2 = {1, 2, 1}; + cout << "Test Case 2: " << sol.shoppingOffers(price2, special2, needs2) << endl; // 11 + + return 0; +}