Skip to content

Commit 40d9972

Browse files
committed
git
1 parent 3b6bfb5 commit 40d9972

File tree

4 files changed

+135
-0
lines changed
  • solutions

4 files changed

+135
-0
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
class Solution:
2+
def maxProfit(
3+
self,
4+
n: int,
5+
present: list[int],
6+
future: list[int],
7+
hierarchy: list[list[int]],
8+
budget: int,
9+
) -> int:
10+
tree = [[] for _ in range(n)]
11+
12+
for u, v in hierarchy:
13+
tree[u - 1].append(v - 1)
14+
15+
@functools.lru_cache(None)
16+
def dp(u: int, parent: int) -> tuple[list[int], list[int]]:
17+
noDiscount = [0] * (budget + 1)
18+
withDiscount = [0] * (budget + 1)
19+
20+
for v in tree[u]:
21+
if v == parent:
22+
continue
23+
childNoDiscount, childWithDiscount = dp(v, u)
24+
noDiscount = self._merge(noDiscount, childNoDiscount)
25+
withDiscount = self._merge(withDiscount, childWithDiscount)
26+
27+
newDp0 = noDiscount[:]
28+
newDp1 = noDiscount[:]
29+
30+
# 1. Buy current node at full cost (no discount)
31+
fullCost = present[u]
32+
for b in range(fullCost, budget + 1):
33+
profit = future[u] - fullCost
34+
newDp0[b] = max(newDp0[b], withDiscount[b - fullCost] + profit)
35+
36+
# 2. Buy current node at half cost (discounted by parent)
37+
halfCost = present[u] // 2
38+
for b in range(halfCost, budget + 1):
39+
profit = future[u] - halfCost
40+
newDp1[b] = max(newDp1[b], withDiscount[b - halfCost] + profit)
41+
42+
return newDp0, newDp1
43+
44+
return max(dp(0, -1)[0])
45+
46+
def _merge(self, dpA: list[int], dpB: list[int]) -> list[int]:
47+
merged = [-math.inf] * len(dpA)
48+
for i, a in enumerate(dpA):
49+
for j in range(len(dpA) - i):
50+
merged[i + j] = max(merged[i + j], a + dpB[j])
51+
return merged
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
class Solution {
2+
public:
3+
string lexicographicallySmallestString(string s) {
4+
const int n = s.size();
5+
// dp[i][j] := the lexicographically smallest string by removing adjacent
6+
// letters from s[i..j)
7+
vector<vector<string>> dp(n + 1, vector<string>(n + 1));
8+
9+
for (int d = 1; d <= n; ++d)
10+
for (int i = 0; i + d <= n; ++i) {
11+
const int j = i + d;
12+
// 1. Keep s[i].
13+
string minString = s[i] + dp[i + 1][j];
14+
// 2. Remove s[i] and s[k] if possible.
15+
for (int k = i + 1; k < j; ++k)
16+
if (isConsecutive(s[i], s[k]) && dp[i + 1][k].empty())
17+
minString = min(minString, dp[k + 1][j]);
18+
dp[i][j] = minString;
19+
}
20+
21+
return dp[0][n];
22+
}
23+
24+
private:
25+
bool isConsecutive(char a, char b) {
26+
return abs(a - b) == 1 || abs(a - b) == 25;
27+
}
28+
};
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
class Solution {
2+
public String lexicographicallySmallestString(String s) {
3+
final int n = s.length();
4+
// dp[i][j]: the lexicographically smallest string by removing adjacent letters from s[i..j)
5+
String[][] dp = new String[n + 1][n + 1];
6+
7+
// Initialize dp[i][i] = "" for all i.
8+
for (int i = 0; i <= n; ++i)
9+
dp[i][i] = "";
10+
11+
for (int d = 1; d <= n; ++d)
12+
for (int i = 0; i + d <= n; ++i) {
13+
final int j = i + d;
14+
// 1. Keep s[i].
15+
String minString = s.charAt(i) + dp[i + 1][j];
16+
// 2. Remove s[i] and s[k] if possible.
17+
for (int k = i + 1; k < j; ++k)
18+
if (isConsecutive(s.charAt(i), s.charAt(k)) && dp[i + 1][k].isEmpty()) {
19+
final String candidate = dp[k + 1][j];
20+
if (candidate.compareTo(minString) < 0)
21+
minString = candidate;
22+
}
23+
dp[i][j] = minString;
24+
}
25+
26+
return dp[0][n];
27+
}
28+
29+
private boolean isConsecutive(char a, char b) {
30+
return Math.abs(a - b) == 1 || Math.abs(a - b) == 25;
31+
}
32+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
class Solution:
2+
def lexicographicallySmallestString(self, s: str) -> str:
3+
n = len(s)
4+
# dp[i][j]: the lexicographically smallest string by removing adjacent
5+
# letters from s[i..j)
6+
dp = [[''] * (n + 1) for _ in range(n + 1)]
7+
8+
for d in range(1, n + 1):
9+
for i in range(n - d + 1):
10+
j = i + d
11+
# 1. Keep s[i].
12+
minString = s[i] + dp[i + 1][j]
13+
# 2. Remove s[i] and s[k] if possible.
14+
for k in range(i + 1, j):
15+
if self._isConsecutive(s[i], s[k]) and dp[i + 1][k] == '':
16+
candidate = dp[k + 1][j]
17+
if candidate < minString:
18+
minString = candidate
19+
dp[i][j] = minString
20+
21+
return dp[0][n]
22+
23+
def _isConsecutive(self, a: str, b: str) -> bool:
24+
return abs(ord(a) - ord(b)) == 1 or abs(ord(a) - ord(b)) == 25

0 commit comments

Comments
 (0)