넘치게 채우기
[LeetCode] 3562. Maximum Profit from Trading Stocks with Discounts 본문
[LeetCode] 3562. Maximum Profit from Trading Stocks with Discounts
riveroverflow 2025. 12. 17. 00:51LeetCode - Maximum Profit from Trading Stocks with Discounts
문제 유형: 다이나믹 프로그래밍, 트리, 그래프
문제 난이도: Hard
문제
You are given an integer n, representing the number of employees in a company. Each employee is assigned a unique ID from 1 to n, and employee 1 is the CEO. You are given two 1-based integer arrays, present and future, each of length n, where:
- present[i] represents the current price at which the ith employee can buy a stock today.
- future[i] represents the expected price at which the ith employee can sell the stock tomorrow.
The company's hierarchy is represented by a 2D integer array hierarchy, where hierarchy[i] = [ui, vi] means that employee ui is the direct boss of employee vi.
Additionally, you have an integer budget representing the total funds available for investment.
However, the company has a discount policy: if an employee's direct boss purchases their own stock, then the employee can buy their stock at half the original price (floor(present[v] / 2)).
Return the maximum profit that can be achieved without exceeding the given budget.
Note:
- You may buy each stock at most once.
- You cannot use any profit earned from future stock prices to fund additional investments and must buy only from budget.
n명의 사원들이 있고, 사원번호는 1~n번으로 주어진다.
1번이 CEO이다.
1-based 정수배열 present, future가 주어진다. present[i]는 i번째 사원이 주식을 사는 비용, future[i]는 i번째 사원이 주식을 팔 때의 비용이다.
회사의 조직도는 [u_i, v_i]꼴로 주어지며, u_i가 v_i의 직속상사라는 뜻이다.
만약 자신의 직속상사가 주식을 산다면, 그 아래 사원은 반값(소수점 버림)으로 살 수 있다.
최대 이익을 구하시오.
단, 사원들은 각각 한번씩만 사고팔 수 있으며, 다른 사람이 사고판 돈으로 추가로 살 수는 없습니다.
풀이
를 참고..
매우 어려운 Tree DP 문제이다.
우선, 1-based를 0-based로 바꾼다.
dp[u][부모가 샀는지여부][사용예산]으로 dp테이블을 정의한다.
우선, 자식들의 케이스들을 먼저 계산한다(postorder)
그 뒤 상사의 구매여부 두 가지 케이스 모두 고려해서,
이번 노드를 사는 경우:
자식들에게 예산 b로 얻을 수 있는 최대 이익을 구한다.
dp[v][0][b]는 아래 자식이 b에서 사는 경우를 말하는데, base라는 이전에 처리한 자식들 값을 기반으로 하위 배낭문제 케이스들을 병합하는 것이다.
이후에, 결과를 반영한다.
price가 이번 예산보다 작거나 같다면, 새로 사는 것을 시도할 수 있다.
새로운 최대 이익을 구한다. 여기서는 dp[v][1][b]를 기반으로, 즉 u에서 구매했으니, 그 자식인 v는 반값에 살 수 있는 것을 반영하여 배낭들을 병합한다.
최종적으로 결과를 dp테이블에 업데이트한다.
dp[0][0]에서 가장 큰 값을 반환한다.
코드
C++
#pragma GCC optimize("O3", "unroll-loops");
static const int __ = [](){
ios::sync_with_stdio(0);
cin.tie(0);
return 0;
}();
class Solution {
public:
const int INF = 1e9;
int n, B;
vector<int> present, future;
vector<vector<int>> adj;
// dp[u][parentbought][budget]
vector<vector<vector<int>>> dp;
void dfs(int u) {
for(int v : adj[u]) {
dfs(v);
}
for(int parentBought = 0; parentBought <= 1; parentBought++) {
int price = parentBought? present[u] / 2 : present[u];
int profit = future[u] - price;
vector<int> curr(B+1, 0);
// u를 안사는 경우
vector<int> base(B+1, 0);
for(int v : adj[u]) {
vector<int> next(B+1, 0);
for(int b1 = 0; b1 <= B; b1++) {
for(int b2 = 0; b1 + b2 <= B; b2++) {
next[b1 + b2] = max(next[b1 + b2], base[b1] + dp[v][0][b2]);
}
}
base.swap(next);
}
for(int b = 0; b <= B; b++) {
curr[b] = base[b];
}
// u를 사는경우
if(price <= B) {
vector<int> baseBuy(B+1, 0);
for(int v : adj[u]) {
vector<int> next(B+1, 0);
for(int b1 = 0; b1 <= B; b1++) {
for(int b2 = 0; b1 + b2 <= B; b2++) {
next[b1 + b2] = max(next[b1 + b2], baseBuy[b1] + dp[v][1][b2]);
}
}
baseBuy.swap(next);
}
for(int b = price; b <= B; b++) {
curr[b] = max(curr[b], baseBuy[b-price] + profit);
}
}
dp[u][parentBought] = move(curr);
}
}
int maxProfit(int n, vector<int>& present, vector<int>& future, vector<vector<int>>& hierarchy, int budget) {
this -> n = n;
this -> B = budget;
this -> present = present;
this -> future = future;
adj.resize(n);
for(auto &h : hierarchy) {
adj[h[0]-1].emplace_back(h[1]-1);
}
dp.resize(n, vector<vector<int>>(2, vector<int>(B+1)));
dfs(0);
int ans = 0;
for(int b = 0; b <= B; b++) {
ans = max(ans, dp[0][0][b]);
}
return ans;
}
};'PS > LeetCode' 카테고리의 다른 글
| [LeetCode] 3577. Count the Number of Computer Unlocking Permutations (0) | 2025.12.10 |
|---|---|
| [LeetCode] 3578. Count Partitions With Max-Min Difference at Most K (0) | 2025.12.06 |
| [LeetCode] 3625. Count Number of Trapezoids II (0) | 2025.12.03 |
| [LeetCode] 3623. Count Number of Trapezoids I (0) | 2025.12.03 |
| [LeetCode] 2141. Maximum Running Time of N Computers (0) | 2025.12.01 |