You are given k projects, each with a capital value and a profit value. You are also given an initial capital. The i-th project requires capital[i] capital to start, and the profit of the i-th project is profits[i]. Once a project is selected, you can invest its capital and start it to get the profit. After each project is finished, you can choose to reinvest the profit back into one of the available projects.

The goal is to maximize your total profit by selecting k projects and starting them with the initial capital, and reinvesting the profits in an optimal way.

Sample Input/Output:


Let’s consider a sample input:

k = 2
W = 0
profits = [1, 2, 3]
capital = [0, 1, 1]

Expected Output:

The maximum profit is 4.

Explanation:
Initially, you have W = 0 capital. You can start the first project with capital[0] = 0, and the profit will be added to the available capital. Afterward, you can start the third project with capital[2] = 1, and the total profit will be 4.

Time and Space Complexity:


The time complexity of the solution will be O(N log N + K log N), where N is the total number of projects. We need to sort the projects based on their capital, which takes O(N log N) time. We also need to maintain a priority queue of potential projects sorted by their profits, which takes O(K log N) time.

The space complexity will be O(N) to store the projects and the priority queue.

Now, let’s implement the solution in C++:

#include <iostream>
#include <vector>
#include <queue>

using namespace std;

struct Project {
    int capital;
    int profit;

    Project(int c, int p) : capital(c), profit(p) {}
};

class CompareByProfit {
public:
    bool operator()(const Project& p1, const Project& p2) {
        return p1.profit < p2.profit;
    }
};

int findMaximizedCapital(int k, int W, vector<int>& profits, vector<int>& capital) {
    vector<Project> projects;
    priority_queue<Project, vector<Project>, CompareByProfit> potentialProjects;

    for (int i = 0; i < profits.size(); ++i) {
        projects.push_back(Project(capital[i], profits[i]));
    }

    sort(projects.begin(), projects.end(), [](const Project& p1, const Project& p2) {
        return p1.capital < p2.capital;
    });

    int i = 0;
    while (k > 0) {
        while (i < projects.size() && projects[i].capital <= W) {
            potentialProjects.push(projects[i]);
            i++;
        }

        if (!potentialProjects.empty()) {
            W += potentialProjects.top().profit;
            potentialProjects.pop();
            k--;
        } else {
            break;
        }
    }

    return W;
}

int main() {
    int k = 2;
    int W = 0;
    vector<int> profits = {1, 2, 3};
    vector<int> capital = {0, 1, 1};

    int maxProfit = findMaximizedCapital(k, W, profits, capital);

    cout << "The maximum profit is " << maxProfit << "." << endl;

    return 0;
}

In this implementation, we use a custom Project struct to store each project’s capital and profit. We sort the projects based on their capital and maintain a priority queue (potentialProjects) of potential projects sorted by their profits.

The findMaximizedCapital function first sorts the projects based on their capital. Then it iterates through the projects, adding potential projects to the priority queue while their capital is less than or equal to the available capital (W). After adding all potential projects, it selects the project with the highest profit from the priority queue and starts it. This process continues until k projects are started or there are no more projects available.

The main function demonstrates the usage of findMaximizedCapital by finding the maximum profit for the given input values.

The output for the provided test case will be:

The maximum profit is 4.