Skip to content

Commit be5b142

Browse files
committed
feat: add solutions to lc problem: No.0879
No.0879.Profitable Schemes
1 parent f891629 commit be5b142

File tree

3 files changed

+290
-2
lines changed

3 files changed

+290
-2
lines changed

solution/0800-0899/0879.Profitable Schemes/README.md

Lines changed: 141 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,22 @@
5353

5454
<!-- 这里可写通用的实现逻辑 -->
5555

56-
**方法一:动态规划**
56+
**方法一:记忆化搜索**
57+
58+
我们设计一个函数 $dfs(i, j, k)$,表示从第 $i$ 个工作开始,且当前已经选择了 $j$ 个员工,且当前产生的利润为 $k$,这种情况下的方案数。那么答案就是 $dfs(0, 0, 0)$。
59+
60+
函数 $dfs(i, j, k)$ 的执行过程如下:
61+
62+
- 如果 $i = n$,表示所有工作都已经考虑过了,如果 $k \geq minProfit$,则方案数为 $1$,否则方案数为 $0$;
63+
- 如果 $i \lt n$,我们可以选择不选择第 $i$ 个工作,此时方案数为 $dfs(i + 1, j, k)$;如果 $j + group[i] \leq n$,我们也可以选择第 $i$ 个工作,此时方案数为 $dfs(i + 1, j + group[i], \min(k + profit[i], minProfit))$。这里我们将利润上限限制在 $minProfit$,是因为利润超过 $minProfit$ 对我们的答案没有任何影响。
64+
65+
最后返回 $dfs(0, 0, 0)$ 即可。
66+
67+
为了避免重复计算,我们可以使用记忆化搜索的方法,用一个三维数组 $f$ 记录所有的 $dfs(i, j, k)$ 的结果。当我们计算出 $dfs(i, j, k)$ 的值后,我们将其存入 $f[i][j][k]$ 中。调用 $dfs(i, j, k)$ 时,如果 $f[i][j][k]$ 已经被计算过,我们直接返回 $f[i][j][k]$ 即可。
68+
69+
时间复杂度 $O(m \times n \times minProfit)$,空间复杂度 $O(m \times n \times minProfit)$。其中 $m$ 和 $n$ 分别为工作的数量和员工的数量,而 $minProfit$ 为至少产生的利润。
70+
71+
**方法二:动态规划**
5772

5873
我们定义 $f[i][j][k]$ 表示前 $i$ 个工作中,选择了不超过 $j$ 个员工,且至少产生 $k$ 的利润的方案数。初始时 $f[0][j][0] = 1$,表示不选择任何工作,且至少产生 $0$ 的利润的方案数为 $1$。答案即为 $f[m][n][minProfit]$。
5974

@@ -69,6 +84,21 @@
6984

7085
<!-- 这里可写当前语言的特殊实现逻辑 -->
7186

87+
```python
88+
class Solution:
89+
def profitableSchemes(self, n: int, minProfit: int, group: List[int], profit: List[int]) -> int:
90+
@cache
91+
def dfs(i: int, j: int, k: int) -> int:
92+
if i >= len(group):
93+
return 1 if k == minProfit else 0
94+
ans = dfs(i + 1, j, k)
95+
if j + group[i] <= n:
96+
ans += dfs(i + 1, j + group[i], min(k + profit[i], minProfit))
97+
return ans % (10**9 + 7)
98+
99+
return dfs(0, 0, 0)
100+
```
101+
72102
```python
73103
class Solution:
74104
def profitableSchemes(self, n: int, minProfit: int, group: List[int], profit: List[int]) -> int:
@@ -92,6 +122,43 @@ class Solution:
92122

93123
<!-- 这里可写当前语言的特殊实现逻辑 -->
94124

125+
```java
126+
class Solution {
127+
private Integer[][][] f;
128+
private int m;
129+
private int n;
130+
private int minProfit;
131+
private int[] group;
132+
private int[] profit;
133+
private final int mod = (int) 1e9 + 7;
134+
135+
public int profitableSchemes(int n, int minProfit, int[] group, int[] profit) {
136+
m = group.length;
137+
this.n = n;
138+
f = new Integer[m][n + 1][minProfit + 1];
139+
this.minProfit = minProfit;
140+
this.group = group;
141+
this.profit = profit;
142+
return dfs(0, 0, 0);
143+
}
144+
145+
private int dfs(int i, int j, int k) {
146+
if (i >= m) {
147+
return k == minProfit ? 1 : 0;
148+
}
149+
if (f[i][j][k] != null) {
150+
return f[i][j][k];
151+
}
152+
int ans = dfs(i + 1, j, k);
153+
if (j + group[i] <= n) {
154+
ans += dfs(i + 1, j + group[i], Math.min(k + profit[i], minProfit));
155+
}
156+
ans %= mod;
157+
return f[i][j][k] = ans;
158+
}
159+
}
160+
```
161+
95162
```java
96163
class Solution {
97164
public int profitableSchemes(int n, int minProfit, int[] group, int[] profit) {
@@ -121,6 +188,33 @@ class Solution {
121188

122189
### **C++**
123190

191+
```cpp
192+
class Solution {
193+
public:
194+
int profitableSchemes(int n, int minProfit, vector<int>& group, vector<int>& profit) {
195+
int m = group.size();
196+
int f[m][n + 1][minProfit + 1];
197+
memset(f, -1, sizeof(f));
198+
const int mod = 1e9 + 7;
199+
function<int(int, int, int)> dfs = [&](int i, int j, int k) -> int {
200+
if (i >= m) {
201+
return k == minProfit ? 1 : 0;
202+
}
203+
if (f[i][j][k] != -1) {
204+
return f[i][j][k];
205+
}
206+
int ans = dfs(i + 1, j, k);
207+
if (j + group[i] <= n) {
208+
ans += dfs(i + 1, j + group[i], min(k + profit[i], minProfit));
209+
}
210+
ans %= mod;
211+
return f[i][j][k] = ans;
212+
};
213+
return dfs(0, 0, 0);
214+
}
215+
};
216+
```
217+
124218
```cpp
125219
class Solution {
126220
public:
@@ -149,6 +243,52 @@ public:
149243

150244
### **Go**
151245

246+
```go
247+
func profitableSchemes(n int, minProfit int, group []int, profit []int) int {
248+
m := len(group)
249+
f := make([][][]int, m)
250+
for i := range f {
251+
f[i] = make([][]int, n+1)
252+
for j := range f[i] {
253+
f[i][j] = make([]int, minProfit+1)
254+
for k := range f[i][j] {
255+
f[i][j][k] = -1
256+
}
257+
}
258+
}
259+
const mod = 1e9 + 7
260+
var dfs func(i, j, k int) int
261+
dfs = func(i, j, k int) int {
262+
if i >= m {
263+
if k >= minProfit {
264+
return 1
265+
}
266+
return 0
267+
}
268+
if f[i][j][k] != -1 {
269+
return f[i][j][k]
270+
}
271+
ans := dfs(i+1, j, k)
272+
if j+group[i] <= n {
273+
ans += dfs(i+1, j+group[i], min(k+profit[i], minProfit))
274+
}
275+
ans %= mod
276+
f[i][j][k] = ans
277+
return ans
278+
}
279+
return dfs(0, 0, 0)
280+
}
281+
282+
func min(a, b int) int {
283+
if a < b {
284+
return a
285+
}
286+
return b
287+
}
288+
```
289+
290+
### **Go**
291+
152292
```go
153293
func profitableSchemes(n int, minProfit int, group []int, profit []int) int {
154294
m := len(group)

solution/0800-0899/0879.Profitable Schemes/README_EN.md

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,50 @@ There are 7 possible schemes: (0), (1), (2), (0,1), (0,2), (1,2), and (0,1,2).</
4141

4242
## Solutions
4343

44+
**Solution 1: recursion with memoization**
45+
46+
We design a function $dfs(i, j, k)$, which means that we start from the $i$-th job, and have chosen $j$ employees, and the current profit is $k$, then the number of schemes in this case is $dfs(0, 0, 0)$.
47+
48+
The execution process of function $dfs(i, j, k)$ is as follows:
49+
50+
- If $i = n$, it means that all the jobs have been considered. If $k \geq minProfit$, the number of schemes is $1$, otherwise the number of schemes is $0$;
51+
- If $i < n$, we can choose not to choose the $i$-th job, then the number of schemes is $dfs(i + 1, j, k)$; if $j + group[i] \leq n$, we can also choose the $i$-th job, then the number of schemes is $dfs(i + 1, j + group[i], \min(k + profit[i], minProfit))$. Here we limit the profit upper limit to $minProfit$, because the profit exceeding $minProfit$ has no effect on our answer.
52+
53+
Finally, return $dfs(0, 0, 0)$.
54+
55+
In order to avoid repeated calculation, we can use the method of memoization. We use a three-dimensional array $f$ to record all the results of $dfs(i, j, k)$. When we calculate the value of $dfs(i, j, k)$, we store it in $f[i][j][k]$. When we call $dfs(i, j, k)$, if $f[i][j][k]$ has been calculated, we return $f[i][j][k]$ directly.
56+
57+
The time complexity is $O(m \times n \times minProfit)$, and th e space complexity is $O(m \times n \times minProfit)$. Here $m$ and $n$ are the number of jobs and employees, and $minProfit$ is the minimum profit.
58+
59+
**Solution 2: Dynamic Programming**
60+
61+
We define $f[i][j][k]$ to be the number of schemes to make a profit of at least $k$ with $i$ jobs and $j$ workers. Initially, we have $f[0][j][0] = 1$, which means that there is only one scheme to make a profit of $0$ without any jobs.
62+
63+
For the $i$-th job, we can choose to work or not to work. If we do not work, then $f[i][j][k] = f[i - 1][j][k]$; if we work, then $f[i][j][k] = f[i - 1][j - group[i - 1]][max(0, k - profit[i - 1])]$. We need to enumerate $j$ and $k$, and add up all the schemes.
64+
65+
The final answer is $f[m][n][minProfit]$.
66+
67+
The time complexity is $O(m \times n \times minProfit)$, and the space complexity is $O(m \times n \times minProfit)$. Here $m$ and $n$ are the numbers of jobs and workers, and $minProfit$ is the minimum profit to make.
68+
4469
<!-- tabs:start -->
4570

4671
### **Python3**
4772

73+
```python
74+
class Solution:
75+
def profitableSchemes(self, n: int, minProfit: int, group: List[int], profit: List[int]) -> int:
76+
@cache
77+
def dfs(i: int, j: int, k: int) -> int:
78+
if i >= len(group):
79+
return 1 if k == minProfit else 0
80+
ans = dfs(i + 1, j, k)
81+
if j + group[i] <= n:
82+
ans += dfs(i + 1, j + group[i], min(k + profit[i], minProfit))
83+
return ans % (10**9 + 7)
84+
85+
return dfs(0, 0, 0)
86+
```
87+
4888
```python
4989
class Solution:
5090
def profitableSchemes(self, n: int, minProfit: int, group: List[int], profit: List[int]) -> int:
@@ -66,6 +106,43 @@ class Solution:
66106

67107
### **Java**
68108

109+
```java
110+
class Solution {
111+
private Integer[][][] f;
112+
private int m;
113+
private int n;
114+
private int minProfit;
115+
private int[] group;
116+
private int[] profit;
117+
private final int mod = (int) 1e9 + 7;
118+
119+
public int profitableSchemes(int n, int minProfit, int[] group, int[] profit) {
120+
m = group.length;
121+
this.n = n;
122+
f = new Integer[m][n + 1][minProfit + 1];
123+
this.minProfit = minProfit;
124+
this.group = group;
125+
this.profit = profit;
126+
return dfs(0, 0, 0);
127+
}
128+
129+
private int dfs(int i, int j, int k) {
130+
if (i >= m) {
131+
return k == minProfit ? 1 : 0;
132+
}
133+
if (f[i][j][k] != null) {
134+
return f[i][j][k];
135+
}
136+
int ans = dfs(i + 1, j, k);
137+
if (j + group[i] <= n) {
138+
ans += dfs(i + 1, j + group[i], Math.min(k + profit[i], minProfit));
139+
}
140+
ans %= mod;
141+
return f[i][j][k] = ans;
142+
}
143+
}
144+
```
145+
69146
```java
70147
class Solution {
71148
public int profitableSchemes(int n, int minProfit, int[] group, int[] profit) {
@@ -95,6 +172,33 @@ class Solution {
95172

96173
### **C++**
97174

175+
```cpp
176+
class Solution {
177+
public:
178+
int profitableSchemes(int n, int minProfit, vector<int>& group, vector<int>& profit) {
179+
int m = group.size();
180+
int f[m][n + 1][minProfit + 1];
181+
memset(f, -1, sizeof(f));
182+
const int mod = 1e9 + 7;
183+
function<int(int, int, int)> dfs = [&](int i, int j, int k) -> int {
184+
if (i >= m) {
185+
return k == minProfit ? 1 : 0;
186+
}
187+
if (f[i][j][k] != -1) {
188+
return f[i][j][k];
189+
}
190+
int ans = dfs(i + 1, j, k);
191+
if (j + group[i] <= n) {
192+
ans += dfs(i + 1, j + group[i], min(k + profit[i], minProfit));
193+
}
194+
ans %= mod;
195+
return f[i][j][k] = ans;
196+
};
197+
return dfs(0, 0, 0);
198+
}
199+
};
200+
```
201+
98202
```cpp
99203
class Solution {
100204
public:
@@ -123,6 +227,50 @@ public:
123227

124228
### **Go**
125229

230+
```go
231+
func profitableSchemes(n int, minProfit int, group []int, profit []int) int {
232+
m := len(group)
233+
f := make([][][]int, m)
234+
for i := range f {
235+
f[i] = make([][]int, n+1)
236+
for j := range f[i] {
237+
f[i][j] = make([]int, minProfit+1)
238+
for k := range f[i][j] {
239+
f[i][j][k] = -1
240+
}
241+
}
242+
}
243+
const mod = 1e9 + 7
244+
var dfs func(i, j, k int) int
245+
dfs = func(i, j, k int) int {
246+
if i >= m {
247+
if k >= minProfit {
248+
return 1
249+
}
250+
return 0
251+
}
252+
if f[i][j][k] != -1 {
253+
return f[i][j][k]
254+
}
255+
ans := dfs(i+1, j, k)
256+
if j+group[i] <= n {
257+
ans += dfs(i+1, j+group[i], min(k+profit[i], minProfit))
258+
}
259+
ans %= mod
260+
f[i][j][k] = ans
261+
return ans
262+
}
263+
return dfs(0, 0, 0)
264+
}
265+
266+
func min(a, b int) int {
267+
if a < b {
268+
return a
269+
}
270+
return b
271+
}
272+
```
273+
126274
```go
127275
func profitableSchemes(n int, minProfit int, group []int, profit []int) int {
128276
m := len(group)

solution/1200-1299/1230.Toss Strange Coins/Solution.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ def probabilityOfHeads(self, prob: List[float], target: int) -> float:
44
f[0] = 1
55
for p in prob:
66
for j in range(target, -1, -1):
7-
f[j] *= (1 - p)
7+
f[j] *= 1 - p
88
if j:
99
f[j] += p * f[j - 1]
1010
return f[target]

0 commit comments

Comments
 (0)