Skip to content

Conversation

@Noob-coder-007
Copy link

🛒 Shopping Offers (DFS + Memoization)
Problem Description

In LeetCode Store, there are n types of items.
Each item has a price, and there are several special bundle offers that let you buy multiple items together for a discounted price.

You are given:

price[i]: cost of the i-th item.

needs[i]: number of units of the i-th item you need.

special[i]: a list where:

the first n elements represent how many of each item are in the bundle,

and the last element is the bundle price.

You must buy exactly the required number of items (not more).
Return the minimum total cost to satisfy all your needs using any combination of bundles and individual purchases.

🧩 Example

Input:

price = [2,5]
special = [[3,0,5],[1,2,10]]
needs = [3,2]

Output: 14

Explanation:

Buy bundle2 (1A + 2B) for $10.

Then buy 2A individually (2 × $2 = $4).

Total = $14.

Approach
🔹 Search Space Definition:

We need to decide how many times to use each special offer to minimize cost.

Each offer can be used any number of times,
as long as it doesn’t exceed our required needs.

🔹 DFS + Memoization:

We define a recursive function:

dfs(currentNeeds) → minimum cost to fulfill these needs

For each call:

Calculate the base cost = buying all items at regular prices.

Try using each special offer:

Check if it’s valid (doesn’t exceed remaining needs).

Subtract the items from needs.

Recursively compute the cost for newNeeds.

Take the minimum cost of all possibilities.

We memoize each needs configuration to avoid recalculating overlapping states.

🔹 Intuition:

This is a search + pruning problem:

At every step, we explore all valid offers that reduce the current needs.

Since the same “needs” state may occur multiple times in different orders,
we cache (memoize) previously computed results for efficiency.

The recursion tree explores all possible combinations,
but memoization ensures each state is processed only once.

⏱️ Complexity:

Time Complexity: O(n * product(needs[i]))
(since each unique combination of remaining needs is visited once)

Space Complexity: O(product(needs[i]))
(for recursion stack + memoization map)

✅ Solution in Code (C++)

#include <bits/stdc++.h>
using namespace std;

class Solution {
public:
    unordered_map<string, int> memo;

    // Convert vector<int> needs into a unique string key for memoization
    string encode(vector<int>& needs) {
        string key;
        for (int x : needs) key += to_string(x) + ",";
        return key;
    }

    // Recursive helper function (DFS)
    int dfs(vector<int>& price, vector<vector<int>>& special, vector<int> needs) {
        string key = encode(needs);
        if (memo.count(key)) return memo[key];

        int n = price.size();
        int minCost = 0;

        // Base case: buy all remaining items at regular prices
        for (int i = 0; i < n; i++) {
            minCost += needs[i] * price[i];
        }

        // Try every special offer
        for (auto& offer : special) {
            vector<int> newNeeds = needs;
            bool valid = true;

            // Check if the offer can be applied
            for (int i = 0; i < n; i++) {
                newNeeds[i] -= offer[i];
                if (newNeeds[i] < 0) { // exceeds need
                    valid = false;
                    break;
                }
            }

            // If valid, consider this offer and recurse
            if (valid) {
                minCost = min(minCost, offer[n] + dfs(price, special, newNeeds));
            }
        }

        memo[key] = minCost;
        return minCost;
    }

    int shoppingOffers(vector<int>& price, vector<vector<int>>& special, vector<int>& needs) {
        memo.clear();
        return dfs(price, special, needs);
    }
};

int main() {
    Solution sol;

    // Test Case 1
    vector<int> price1 = {2, 5};
    vector<vector<int>> special1 = {{3, 0, 5}, {1, 2, 10}};
    vector<int> needs1 = {3, 2};
    cout << "Test Case 1: " << sol.shoppingOffers(price1, special1, needs1) << endl; // 14

    // Test Case 2
    vector<int> price2 = {2, 3, 4};
    vector<vector<int>> special2 = {{1, 1, 0, 4}, {2, 2, 1, 9}};
    vector<int> needs2 = {1, 2, 1};
    cout << "Test Case 2: " << sol.shoppingOffers(price2, special2, needs2) << endl; // 11

    return 0;
}

Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for raising the PR, the owner will be review it soon' keep patience, keep contributing>>>!!! make sure you have star ⭐ the repo

@SjxSubham
Copy link
Owner

SjxSubham commented Oct 4, 2025

Raise a Issue first regarding problem statement like #75 then add solution by raising a PR... check other closed issues as well for ref.

Fix the PR description as well,, it should maintain proper formatting chk others PRs as well...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants