Skip to content

Commit 68d0937

Browse files
committed
leetcode
1 parent 364ce93 commit 68d0937

File tree

3 files changed

+226
-0
lines changed

3 files changed

+226
-0
lines changed

SoupServings/soup_servings.dart

+119
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
/*
2+
3+
4+
-* 808. Soup Servings *-
5+
6+
7+
8+
There are two types of soup: type A and type B. Initially, we have n ml of each type of soup. There are four kinds of operations:
9+
10+
Serve 100 ml of soup A and 0 ml of soup B,
11+
Serve 75 ml of soup A and 25 ml of soup B,
12+
Serve 50 ml of soup A and 50 ml of soup B, and
13+
Serve 25 ml of soup A and 75 ml of soup B.
14+
When we serve some soup, we give it to someone, and we no longer have it. Each turn, we will choose from the four operations with an equal probability 0.25. If the remaining volume of soup is not enough to complete the operation, we will serve as much as possible. We stop once we no longer have some quantity of both types of soup.
15+
16+
Note that we do not have an operation where all 100 ml's of soup B are used first.
17+
18+
Return the probability that soup A will be empty first, plus half the probability that A and B become empty at the same time. Answers within 10-5 of the actual answer will be accepted.
19+
20+
21+
22+
Example 1:
23+
24+
Input: n = 50
25+
Output: 0.62500
26+
Explanation: If we choose the first two operations, A will become empty first.
27+
For the third operation, A and B will become empty at the same time.
28+
For the fourth operation, B will become empty first.
29+
So the total probability of A becoming empty first plus half the probability that A and B become empty at the same time, is 0.25 * (1 + 1 + 0.5 + 0) = 0.625.
30+
Example 2:
31+
32+
Input: n = 100
33+
Output: 0.71875
34+
35+
36+
Constraints:
37+
38+
0 <= n <= 109
39+
40+
*/
41+
42+
import 'dart:collection';
43+
44+
// Recursion is BAD in Dart
45+
46+
class A {
47+
double soupServings(int n) {
48+
double ans = solve(n, n);
49+
return ans;
50+
}
51+
52+
double solve(int soupA, int soupB) {
53+
if (soupA <= 0 && soupB <= 0) return 0.5;
54+
if (soupA <= 0) return 1.0;
55+
if (soupB <= 0) return 0.0;
56+
57+
double prob = 0.0;
58+
prob += 0.25 * solve(soupA - 100, soupB);
59+
prob += 0.25 * solve(soupA - 75, soupB - 25);
60+
prob += 0.25 * solve(soupA - 50, soupB - 50);
61+
prob += 0.25 * solve(soupA - 25, soupB - 75);
62+
63+
return prob;
64+
}
65+
}
66+
67+
// Memoization - Dynamic Programming
68+
class Solution {
69+
double soupServings(int n) {
70+
if (n >= 5000) return 1.0;
71+
final HashMap<String, double> dp = HashMap();
72+
double ans = solve(n, n, dp);
73+
return ans;
74+
}
75+
76+
double solve(
77+
final int soupA, final int soupB, final HashMap<String, double> dp) {
78+
if (soupA <= 0 && soupB <= 0) return 0.5;
79+
if (soupA <= 0) return 1.0;
80+
if (soupB <= 0) return 0.0;
81+
82+
String key = soupA.toString() + "-" + soupB.toString();
83+
if (dp.containsKey(key)) return dp[key] ?? 0;
84+
85+
double prob = 0.0;
86+
prob += 0.25 * solve(soupA - 100, soupB, dp);
87+
prob += 0.25 * solve(soupA - 75, soupB - 25, dp);
88+
prob += 0.25 * solve(soupA - 50, soupB - 50, dp);
89+
prob += 0.25 * solve(soupA - 25, soupB - 75, dp);
90+
91+
dp[key] = prob;
92+
return prob;
93+
}
94+
}
95+
96+
// Depth First Search
97+
98+
class B {
99+
final List<List<double>> dp =
100+
List.generate(200, (_) => List.filled(200, 0.0));
101+
102+
double depthFirstSearch(int soupA, int soupB) {
103+
if (soupA <= 0 && soupB <= 0) return 0.5;
104+
if (soupA <= 0) return 1.0;
105+
if (soupB <= 0) return 0.0;
106+
if (dp[soupA][soupB] > 0) return dp[soupA][soupB];
107+
return dp[soupA][soupB] = (depthFirstSearch(soupA - 4, soupB) +
108+
depthFirstSearch(soupA - 3, soupB - 1) +
109+
depthFirstSearch(soupA - 2, soupB - 2) +
110+
depthFirstSearch(soupA - 1, soupB - 3)) /
111+
4;
112+
}
113+
114+
double soupServings(int n) {
115+
if (n > 4800.0) return 1.0;
116+
n = (n + 24.0) ~/ 25.0;
117+
return depthFirstSearch(n, n);
118+
}
119+
}

SoupServings/soup_servings.go

+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package main
2+
3+
/* Recursion is Still BAD in GO - TLE
4+
func soupServings(n int) float64 {
5+
ans := solve(n, n)
6+
return ans
7+
}
8+
9+
func solve(soupA, soupB int) float64 {
10+
if soupA <= 0 && soupB <= 0 {
11+
return 0.5
12+
}
13+
if soupA <= 0 {
14+
return 1.0
15+
}
16+
if soupB <= 0 {
17+
return 0.0
18+
}
19+
20+
var prob float64
21+
prob += 0.25 * solve(soupA-100, soupB)
22+
prob += 0.25 * solve(soupA-75, soupB-25)
23+
prob += 0.25 * solve(soupA-50, soupB-50)
24+
prob += 0.25 * solve(soupA-25, soupB-75)
25+
26+
return prob
27+
}
28+
*/
29+
30+
/*
31+
// Memoization + DP
32+
33+
func soupServings(n int) float64 {
34+
if n > 5000 {
35+
// If n is greater than 5000, the probability is very close to 1.0.
36+
return 1.0
37+
}
38+
39+
// Use a map to store memoized results.
40+
memo := make(map[[2]int]float64)
41+
ans := solve(n, n, memo)
42+
return ans
43+
}
44+
45+
func solve(soupA, soupB int, memo map[[2]int]float64) float64 {
46+
if soupA <= 0 && soupB <= 0 {
47+
return 0.5
48+
}
49+
if soupA <= 0 {
50+
return 1.0
51+
}
52+
if soupB <= 0 {
53+
return 0.0
54+
}
55+
56+
// Check if the result is already memoized.
57+
if val, ok := memo[[2]int{soupA, soupB}]; ok {
58+
return val
59+
}
60+
61+
var prob float64
62+
prob += 0.25 * solve(soupA-100, soupB, memo)
63+
prob += 0.25 * solve(soupA-75, soupB-25, memo)
64+
prob += 0.25 * solve(soupA-50, soupB-50, memo)
65+
prob += 0.25 * solve(soupA-25, soupB-75, memo)
66+
67+
// Memoize the result before returning.
68+
memo[[2]int{soupA, soupB}] = prob
69+
70+
return prob
71+
}
72+
73+
*/
74+
75+
func soupServings(n int) float64 {
76+
if n > 5000 {
77+
return 1.0
78+
}
79+
80+
// Initialize dp memoization
81+
dp := make([][]float64, 200)
82+
for i := 0; i < 200; i++ {
83+
dp[i] = make([]float64, 200)
84+
}
85+
86+
// Define the recursive function depthFirstSearch
87+
var depthFirstSearch func(soupA, soupB int) float64
88+
depthFirstSearch = func(soupA, soupB int) float64 {
89+
if soupA <= 0 && soupB <= 0 {
90+
return 0.5
91+
} else if soupA <= 0 {
92+
return 1.0
93+
} else if soupB <= 0 {
94+
return 0.0
95+
}
96+
97+
if dp[soupA][soupB] > 0 {
98+
return dp[soupA][soupB]
99+
}
100+
101+
dp[soupA][soupB] = 0.25 * (depthFirstSearch(soupA-4, soupB) + depthFirstSearch(soupA-3, soupB-1) + depthFirstSearch(soupA-2, soupB-2) + depthFirstSearch(soupA-1, soupB-3))
102+
return dp[soupA][soupB]
103+
}
104+
105+
// Call dfs and return the result
106+
return depthFirstSearch((n+24)/25, (n+24)/25)
107+
}

SoupServings/soup_servings.md

Whitespace-only changes.

0 commit comments

Comments
 (0)