-
Notifications
You must be signed in to change notification settings - Fork 119
/
Copy pathStone Game II.rs
59 lines (51 loc) · 1.58 KB
/
Stone Game II.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
// Runtime: 0 ms (Top 100.0%) | Memory: 2.40 MB (Top 25.0%)
impl Solution {
pub fn stone_game_ii(piles: Vec<i32>) -> i32 {
let mut cache = vec![vec![None; piles.len()+1]; piles.len()+1];
GameState::new(&mut cache, &piles).best_outcome().0
}
}
struct GameState<'a> {
cache: &'a mut Vec<Vec<Option<(i32, i32)>>>,
piles: &'a [i32],
m: usize,
}
impl<'a, 'b> GameState<'a> {
fn new(cache: &'a mut Vec<Vec<Option<(i32, i32)>>>, piles: &'a [i32]) -> Self {
Self {
cache,
piles,
m: 1,
}
}
fn next_state(&'b mut self, x: usize) -> GameState<'b> {
GameState {
cache: &mut self.cache,
piles: &self.piles[x..],
m: self.m.max(x),
}
}
fn best_outcome(mut self) -> (i32, i32) {
let n = self.piles.len();
let maybe_cached_outcome = self
.cache
.get(n)
.and_then(|row| row.get(self.m.min(n)))
.and_then(|&outcome| outcome);
if let Some(outcome) = maybe_cached_outcome {
return outcome;
}
let max_x = n.min(2 * self.m);
let mut taken = 0;
let mut best_outcome = (0, 0);
for x in (1..=max_x) {
taken += self.piles[x-1];
let future_outcome = self.next_state(x).best_outcome();
if taken + future_outcome.1 > best_outcome.0 {
best_outcome = (taken+future_outcome.1, future_outcome.0);
}
}
self.cache[n][self.m.min(n)] = Some(best_outcome);
best_outcome
}
}