Skip to main content

dp/
lib.rs

1//! # Dynamic Programming
2
3#![feature(test)]
4
5extern crate test;
6
7/// 115h Distinct Subsequences
8struct Sol115;
9
10impl Sol115 {
11    pub fn num_distinct(s: String, t: String) -> i32 {
12        let mut rst = 0;
13        let (s, t) = (s.as_bytes(), t.as_bytes());
14        let mut mem = vec![vec![-1; t.len()]; s.len()];
15
16        fn count(s: &[u8], i: usize, j: usize, t: &[u8], mem: &mut Vec<Vec<i32>>) -> i32 {
17            if j + 1 >= t.len() {
18                return 1;
19            }
20            if i >= s.len() {
21                return 0;
22            }
23
24            if mem[i][j] != -1 {
25                return mem[i][j];
26            }
27
28            let mut rst = 0;
29            for p in i + 1..s.len() {
30                if s[p] == t[j + 1] && s.len() + j + 1 >= t.len() + p {
31                    rst += count(s, p, j + 1, t, mem);
32                }
33            }
34            mem[i][j] = rst;
35            rst
36        }
37
38        for p in 0..s.len() {
39            if s[p] == t[0] && s.len() >= t.len() + p {
40                rst += count(s, p, 0, t, &mut mem);
41            }
42        }
43
44        println!("-> {:?}", mem);
45
46        rst
47    }
48}
49
50/// 132h Palindrome Partitioning II
51struct Sol132;
52
53impl Sol132 {
54    pub fn min_cut(s: String) -> i32 {
55        let s = s.as_bytes();
56
57        let mut palindrome = vec![vec![true; s.len()]; s.len()];
58        for l in (0..s.len()).rev() {
59            for r in l + 1..s.len() {
60                palindrome[l][r] = s[l] == s[r] && palindrome[l + 1][r - 1];
61            }
62        }
63
64        println!("-> {:?}", palindrome);
65
66        let mut dp = vec![i32::MAX; s.len()];
67        for r in 0..s.len() {
68            if palindrome[0][r] {
69                dp[r] = 0;
70            } else {
71                for l in 0..r {
72                    if palindrome[l + 1][r] {
73                        dp[r] = dp[r].min(dp[l] + 1);
74                    }
75                }
76            }
77        }
78
79        dp[s.len() - 1]
80    }
81}
82
83/// 174h Dungeon Game
84struct Sol174;
85
86impl Sol174 {
87    pub fn calculate_minimum_hp(dungeon: Vec<Vec<i32>>) -> i32 {
88        let (rows, cols) = (dungeon.len(), dungeon[0].len());
89        let mut health = vec![vec![i32::MAX; cols + 1]; rows + 1];
90
91        health[rows][cols - 1] = 1;
92        health[rows - 1][cols] = 1;
93
94        for r in (0..rows).rev() {
95            for c in (0..cols).rev() {
96                let x = health[r + 1][c].min(health[r][c + 1]) - dungeon[r][c];
97                health[r][c] = if x <= 0 { 1 } else { x };
98            }
99        }
100
101        println!("-> {:?}", health);
102
103        health[0][0]
104    }
105}
106
107/// 312h Burst Balloons
108struct Sol312;
109
110impl Sol312 {
111    pub fn max_coins(nums: Vec<i32>) -> i32 {
112        let mut mem = vec![vec![0; nums.len()]; nums.len()];
113
114        fn search(mem: &mut Vec<Vec<i32>>, nums: &Vec<i32>, i: usize, j: usize) -> i32 {
115            if i > j {
116                return 0;
117            }
118
119            if i == j {
120                let mut coins = nums[i];
121                if i > 0 {
122                    coins *= nums[i - 1];
123                }
124                if j < nums.len() - 1 {
125                    coins *= nums[j + 1];
126                }
127                return coins;
128            }
129
130            if mem[i][j] > 0 {
131                return mem[i][j];
132            }
133
134            let mut xcoins = 0;
135            for k in i..=j {
136                let mut coins = nums[k];
137                if i > 0 {
138                    coins *= nums[i - 1];
139                }
140                if j < nums.len() - 1 {
141                    coins *= nums[j + 1];
142                }
143
144                if k > 0 {
145                    coins += search(mem, nums, i, k - 1);
146                }
147                coins += search(mem, nums, k + 1, j);
148
149                xcoins = xcoins.max(coins);
150            }
151            mem[i][j] = xcoins;
152
153            xcoins
154        }
155
156        search(&mut mem, &nums, 0, nums.len() - 1)
157    }
158}
159
160/// 329h Longest Increasing Path in a Matrix
161struct Sol329 {}
162
163impl Sol329 {
164    // 1 <= M, N <= 2000
165    // 0 <= M_ij <= 2^31 - 1
166    pub fn longest_increasing_path(matrix: Vec<Vec<i32>>) -> i32 {
167        let mut dp = vec![vec![0; matrix[0].len()]; matrix.len()];
168
169        fn dfs((r, c): (usize, usize), matrix: &[Vec<i32>], dp: &mut [Vec<i32>]) {
170            println!("-> {:?}", (r, c));
171
172            if dp[r][c] != 0 {
173                return;
174            }
175
176            let v = matrix[r][c];
177
178            let mut steps = 1;
179            dp[r][c] = steps;
180
181            let dirs = [-1, 0, 1, 0, -1];
182            for d in 0..4 {
183                let (r, c) = (
184                    r.wrapping_add_signed(dirs[d]),
185                    c.wrapping_add_signed(dirs[d + 1]),
186                );
187
188                if r < matrix.len() && c < matrix[r].len() {
189                    println!("-> . {:?}", (r, c));
190
191                    if matrix[r][c] > v {
192                        if dp[r][c] == 0 {
193                            dfs((r, c), matrix, dp);
194                        }
195
196                        steps = steps.max(dp[r][c] + 1);
197                    }
198                }
199            }
200
201            dp[r][c] = steps;
202        }
203
204        for (r, rows) in matrix.iter().enumerate() {
205            for c in 0..rows.len() {
206                if dp[r][c] == 0 {
207                    dfs((r, c), &matrix, &mut dp);
208                }
209            }
210        }
211
212        println!("-> {dp:?}");
213
214        if let Some(&max) = dp.iter().flatten().max() {
215            return max;
216        }
217        1
218    }
219}
220
221/// 368m Largest Divisible Subset
222struct Sol368;
223
224impl Sol368 {
225    pub fn largest_divisible_subset(nums: Vec<i32>) -> Vec<i32> {
226        let mut dp = vec![1; nums.len()];
227
228        let mut nums = nums;
229        nums.sort_unstable();
230
231        println!("-> {:?}", nums);
232
233        let mut longest = (1, 0);
234        for i in 0..nums.len() {
235            for j in 0..i {
236                if nums[i] % nums[j] == 0 {
237                    dp[i] = dp[i].max(dp[j] + 1);
238
239                    if dp[i] > longest.0 {
240                        longest = (dp[i], i);
241                    }
242                }
243            }
244        }
245
246        println!("-> {:?}", (longest, &dp));
247
248        let mut rst = vec![];
249
250        let mut n = nums[longest.1];
251        for i in (0..=longest.1).rev() {
252            if dp[i] == longest.0 && n % nums[i] == 0 {
253                rst.push(nums[i]);
254                n = nums[i];
255                longest.0 -= 1;
256            }
257        }
258        rst.reverse();
259
260        rst
261    }
262}
263
264/// 377m Combination Sum IV
265struct Sol377;
266
267impl Sol377 {
268    pub fn combination_sum4(nums: Vec<i32>, target: i32) -> i32 {
269        let mut sums = vec![];
270        sums.push(1);
271
272        for t in 1..=target {
273            sums.push(
274                nums.iter()
275                    .filter(|&n| t - n >= 0)
276                    .map(|n| sums[(t - n) as usize])
277                    .sum(),
278            );
279        }
280
281        println!("-> {:?}", sums);
282        sums[target as usize]
283    }
284}
285
286/// 516m Longest Palindromic Subsequence
287struct Sol516;
288
289impl Sol516 {
290    pub fn longest_palindrome_subseq(s: String) -> i32 {
291        let s = s.as_bytes();
292
293        let mut lps = vec![vec![0; s.len()]; s.len()];
294        for x in 0..s.len() {
295            lps[x][x] = 1;
296            for y in (0..x).rev() {
297                lps[x][y] = match s[x] == s[y] {
298                    true => lps[x - 1][y + 1] + 2,
299                    _ => lps[x - 1][y].max(lps[x][y + 1]),
300                };
301            }
302        }
303
304        println!("-> {:?}", lps);
305
306        // Longest Common Subsequence
307        let mut lcs = vec![vec![0; s.len() + 1]; s.len() + 1];
308        for x in 0..s.len() {
309            for y in 0..s.len() {
310                lcs[x + 1][y + 1] = match s[x] == s[s.len() - 1 - y] {
311                    true => lcs[x][y] + 1,
312                    _ => lcs[x][y + 1].max(lcs[x + 1][y]),
313                }
314            }
315        }
316        println!("-> {} {:?}", lcs[s.len()][s.len()], lcs);
317
318        lps[s.len() - 1][0]
319    }
320}
321
322/// 639h Decode Ways II
323struct Sol639 {}
324
325impl Sol639 {
326    /// 1 <= N <= 10^5
327    pub fn num_decodings(s: String) -> i32 {
328        let s: Vec<_> = s.chars().collect();
329        const M: i64 = 1e9 as i64 + 7;
330
331        let mut dp = vec![0; s.len() + 1];
332        dp[0] = 1;
333        dp[1] = match s[0] {
334            '*' => 9,
335            '0' => 0,
336            _ => 1,
337        };
338
339        for (i, &chr) in s.iter().enumerate().skip(1) {
340            match chr {
341                '*' => {
342                    dp[i + 1] = 9 * dp[i] % M;
343                    dp[i + 1] += match s[i - 1] {
344                        '1' => 9 * dp[i - 1] % M,
345                        '2' => 6 * dp[i - 1] % M,
346                        '*' => 15 * dp[i - 1] % M,
347                        _ => 0,
348                    };
349                }
350                _ => {
351                    dp[i + 1] = if chr != '0' { dp[i] } else { 0 };
352                    dp[i + 1] += match s[i - 1] {
353                        '1' => dp[i - 1],
354                        '2' => {
355                            if s[i] <= '6' {
356                                dp[i - 1]
357                            } else {
358                                0
359                            }
360                        }
361                        '*' => (if s[i] <= '6' { 2 } else { 1 }) * dp[i - 1] % M,
362                        _ => 0,
363                    };
364                }
365            }
366        }
367
368        println!("-> {dp:?}");
369        (dp[s.len()] % M) as _
370    }
371}
372
373/// 730h Count Different Palindromic Subsequences
374struct Sol730;
375
376impl Sol730 {
377    /// 1 <= N <= 1000
378    /// 'a'|'b'|'c'|'d'
379    pub fn count_palindromic_subsequences(s: String) -> i32 {
380        use std::collections::HashMap;
381
382        let mut mem = HashMap::new();
383        let chrs: Vec<_> = s.chars().collect();
384
385        const M: i64 = 1e9 as i64 + 7;
386
387        fn search(
388            start: usize,
389            end: usize,
390            chrs: &[char],
391            mem: &mut HashMap<[usize; 2], i64>,
392        ) -> i64 {
393            if start >= end {
394                return 0;
395            }
396
397            if let Some(&count) = mem.get(&[start, end]) {
398                return count;
399            }
400
401            let mut count = 0;
402            for chr in 'a'..='d' {
403                match (
404                    chrs[start..end].iter().position(|&v| v == chr),
405                    chrs[start..end].iter().rev().position(|&v| v == chr),
406                ) {
407                    (None, None) => continue,
408                    (Some(l), Some(r)) => {
409                        let r = end - start - r - 1;
410                        println!("{start}   {l} {chr} {r}   {end}");
411                        if l == r {
412                            count += 1;
413                        } else {
414                            count += 2 + search(start + l + 1, start + r, chrs, mem);
415                        }
416                    }
417                    (_, _) => {}
418                }
419                count %= M;
420            }
421
422            mem.insert([start, end], count);
423            println!("-> {mem:?}");
424
425            count
426        }
427
428        search(0, chrs.len(), &chrs, &mut mem) as _
429    }
430}
431
432/// 790m Domino and Tromino Tiling
433struct Sol790;
434
435impl Sol790 {
436    // 1 <= n <= 10000
437    pub fn num_tilings(n: i32) -> i32 {
438        fn two_states(n: i32) -> i32 {
439            if n == 1 || n == 2 {
440                return n;
441            }
442
443            let mut full = [0; 1000 + 1]; // full cover
444            let mut lshape = [0; 1000 + 1]; // L shape cover
445
446            (full[1], full[2], lshape[2]) = (1, 2, 1);
447
448            const M: i64 = 1e9 as i64 + 7;
449            for i in 3..=n as usize {
450                full[i] = (full[i - 1] + full[i - 2] + 2 * lshape[i - 1]) % M;
451                lshape[i] = (lshape[i - 1] + full[i - 2]) % M;
452            }
453
454            full[n as usize] as _
455        }
456        println!(":: {}", two_states(n));
457
458        if n == 1 || n == 2 {
459            return n;
460        }
461
462        const M: i64 = 1e9 as i64 + 7;
463        let mut dp = vec![0; n as usize + 1];
464
465        (dp[1], dp[2], dp[3]) = (1, 2, 5);
466        for i in 4..=n as usize {
467            dp[i] = (2 * dp[i - 1] + dp[i - 3]) % M;
468        }
469
470        println!("-> {:?}", dp);
471
472        dp[n as usize] as _
473    }
474}
475
476/// 808m Soup Servings
477struct Sol808 {}
478
479impl Sol808 {
480    pub fn soup_servings(n: i32) -> f64 {
481        use std::collections::HashMap;
482
483        let n = (n + 24) / 25;
484        let mut memo = HashMap::new();
485
486        fn search(a: i32, b: i32, memo: &mut HashMap<(i32, i32), f64>) -> f64 {
487            if a <= 0 && b <= 0 {
488                return 0.5;
489            }
490            if a <= 0 {
491                return 1.0;
492            }
493            if b <= 0 {
494                return 0.0;
495            }
496
497            if let Some(&p) = memo.get(&(a, b)) {
498                return p;
499            }
500
501            let p = (search(a - 4, b, memo)
502                + search(a - 3, b - 1, memo)
503                + search(a - 2, b - 2, memo)
504                + search(a - 1, b - 3, memo))
505                / 4.0;
506            memo.insert((a, b), p);
507
508            p
509        }
510
511        for n in 1..=n {
512            if search(n, n, &mut memo) > 1.0 - 0.00001 {
513                return 1.0;
514            }
515        }
516
517        search(n, n, &mut memo)
518    }
519}
520
521/// 873m Length of Longest Fibonacci Subsequence
522struct Sol873;
523
524impl Sol873 {
525    pub fn len_longest_fib_subseq(arr: Vec<i32>) -> i32 {
526        use std::collections::HashSet;
527
528        let mut hset = HashSet::new();
529        for n in &arr {
530            hset.insert(n);
531        }
532
533        println!("-> {:?}", hset);
534
535        let mut xlen = 0;
536        for l in 0..arr.len() {
537            for r in l + 1..arr.len() {
538                let mut prv = arr[r];
539                let mut cur = arr[l] + arr[r];
540
541                let mut clen = 2;
542                while hset.contains(&cur) {
543                    (prv, cur) = (cur, prv + cur);
544
545                    clen += 1;
546                    xlen = xlen.max(clen);
547                }
548            }
549        }
550
551        xlen
552    }
553}
554
555/// 1039m Minimum Score Triangulation of Polygon
556struct Sol1039 {}
557
558impl Sol1039 {
559    pub fn min_score_triangulation(values: Vec<i32>) -> i32 {
560        use std::collections::HashMap;
561
562        let mut cache = HashMap::new();
563        fn search(
564            cache: &mut HashMap<(usize, usize), i32>,
565            i: usize,
566            j: usize,
567            values: &[i32],
568        ) -> i32 {
569            if i + 2 > j {
570                return 0;
571            }
572            if i + 2 == j {
573                return values[i] * values[(i + 1) & (j - 1)] * values[j];
574            }
575
576            if let Some(&score) = cache.get(&(i, j)) {
577                score
578            } else {
579                let score = (i + 1..j)
580                    .map(|k| {
581                        search(cache, i, k, values)
582                            + values[i] * values[k] * values[j]
583                            + search(cache, k, j, values)
584                    })
585                    .min()
586                    .unwrap();
587                cache.insert((i, j), score);
588                score
589            }
590        }
591
592        let score = search(&mut cache, 0, values.len() - 1, &values);
593        println!("-> {cache:?}");
594
595        score
596    }
597}
598
599/// 1092h Shortest Common Supersequence
600struct Sol1092;
601
602impl Sol1092 {
603    /// 1 <= Len_1, Len_2 <= 1000
604    pub fn shortest_common_supersequence(str1: String, str2: String) -> String {
605        let (str1, str2) = (str1.as_bytes(), str2.as_bytes());
606
607        // Longest Common Subsequence
608        let mut dp = vec![vec![0; str2.len() + 1]; str1.len() + 1];
609        for (x, chr1) in str1.iter().enumerate() {
610            for (y, chr2) in str2.iter().enumerate() {
611                dp[x + 1][y + 1] = match chr1 == chr2 {
612                    true => dp[x][y] + 1,
613                    false => dp[x][y + 1].max(dp[x + 1][y]),
614                };
615            }
616        }
617
618        println!("-> LCS :: {:?}", dp);
619
620        let mut rst = vec![];
621        let (mut x, mut y) = (str1.len(), str2.len());
622        while x > 0 || y > 0 {
623            if x > 0 && y > 0 && str1[x - 1] == str2[y - 1] {
624                rst.push(str1[x - 1]);
625                x -= 1;
626                y -= 1;
627            } else if x > 0 && (y == 0 || dp[x - 1][y] >= dp[x][y - 1]) {
628                rst.push(str1[x - 1]);
629                x -= 1;
630            } else if y > 0 {
631                rst.push(str2[y - 1]);
632                y -= 1;
633            }
634        }
635        rst.reverse();
636
637        String::from_utf8(rst).expect("")
638    }
639
640    /// Recursive Memoization (!MLE)
641    pub fn scs_recursive(str1: String, str2: String) -> String {
642        use std::collections::HashMap;
643
644        let mut mem = HashMap::new();
645        fn search<'l>(
646            str1: &'l str,
647            str2: &'l str,
648            mem: &mut HashMap<(&'l str, &'l str), String>,
649        ) -> String {
650            match (str1.len(), str2.len()) {
651                (0, 0) => "".to_string(),
652                (0, _) => str2.to_string(),
653                (_, 0) => str1.to_string(),
654                _ => {
655                    println!("-> {:?}", (&str1, &str2));
656
657                    if let Some(rst) = mem.get(&(str1, str2)) {
658                        return rst.to_string();
659                    }
660
661                    match str1[0..1].cmp(&str2[0..1]) {
662                        std::cmp::Ordering::Equal => {
663                            let scs = search(&str1[1..], &str2[1..], mem);
664                            mem.insert((str1, str2), str1[0..1].to_string() + &*scs);
665                        }
666                        _ => {
667                            let scs1 = search(&str1[1..], str2, mem);
668                            let scs2 = search(str1, &str2[1..], mem);
669
670                            if scs1.len() <= scs2.len() {
671                                mem.insert((str1, str2), str1[0..1].to_string() + &*scs1);
672                            } else {
673                                mem.insert((str1, str2), str2[0..1].to_string() + &*scs2);
674                            }
675                        }
676                    }
677
678                    mem[&(str1, str2)].to_string()
679                }
680            }
681        }
682
683        let rst = search(&str1, &str2, &mut mem);
684        println!("-> {:?}", mem);
685
686        rst
687    }
688}
689
690/// 1277m Count Square Submatrices with All Ones
691struct Sol1277 {}
692
693impl Sol1277 {
694    pub fn count_squares(matrix: Vec<Vec<i32>>) -> i32 {
695        use std::cmp::min;
696
697        let (cols, rows) = (matrix[0].len(), matrix.len());
698
699        let mut counts = vec![vec![0; cols + 1]; rows + 1];
700        let mut count = 0;
701
702        for r in 0..rows {
703            for c in 0..cols {
704                if matrix[r][c] == 1 {
705                    counts[r + 1][c + 1] =
706                        1 + min(counts[r][c], min(counts[r + 1][c], counts[r][c + 1]));
707                    count += counts[r + 1][c + 1];
708                }
709            }
710        }
711
712        count
713    }
714}
715
716/// 1504m Count Submatrices With All Ones
717struct Sol1504 {}
718
719impl Sol1504 {
720    pub fn num_submat(mat: Vec<Vec<i32>>) -> i32 {
721        let cols = mat[0].len();
722
723        let mut count = 0;
724        let mut counts = vec![0; cols * cols];
725
726        for row in mat.iter() {
727            for c in 0..cols {
728                let mut flag = true;
729                for k in 0..=c {
730                    if flag && row[c - k] == 0 {
731                        flag = false;
732                    }
733
734                    if flag {
735                        counts[c * cols + k] += 1;
736                        count += counts[c * cols + k];
737                    } else {
738                        counts[c * cols + k] = 0;
739                    }
740                }
741            }
742        }
743
744        count
745    }
746}
747
748/// 1524m Number of Sub-arrays With Odd Sum
749struct Sol1524;
750
751impl Sol1524 {
752    /// 1 <= N <= 10^5, 1 <= N_i <= 100
753    pub fn num_of_subarrays(arr: Vec<i32>) -> i32 {
754        const M: u32 = 1e9 as u32 + 7;
755
756        let mut edp = vec![0; arr.len()]; // evens
757        let mut odp = vec![0; arr.len()]; // odds
758
759        match arr[arr.len() - 1] & 1 {
760            1 => odp[arr.len() - 1] = 1,
761            _ => edp[arr.len() - 1] = 1,
762        }
763
764        for i in (0..arr.len() - 1).rev() {
765            match arr[i] & 1 {
766                1 => {
767                    odp[i] = (1 + edp[i + 1]) % M;
768                    edp[i] = odp[i + 1];
769                }
770                _ => {
771                    edp[i] = (1 + edp[i + 1]) % M;
772                    odp[i] = odp[i + 1];
773                }
774            }
775        }
776
777        println!("-> {:?}", odp);
778
779        (odp.into_iter().sum::<u32>() % M) as i32
780    }
781
782    fn num_of_subarrays_psum(arr: Vec<i32>) -> i32 {
783        const M: i32 = 1e9 as i32 + 7;
784
785        let mut count = 0;
786        let (mut evens, mut odds) = (1, 0);
787
788        let mut psum = 0;
789        for n in arr {
790            psum += n;
791
792            count += match psum & 1 {
793                1 => {
794                    odds += 1;
795                    evens
796                }
797                _ => {
798                    evens += 1;
799                    odds
800                }
801            } % M;
802        }
803
804        count % M
805    }
806}
807
808/// 1749m Maximum Absolute Sum of Any Subarray
809struct Sol1749;
810
811impl Sol1749 {
812    pub fn max_absolute_sum(nums: Vec<i32>) -> i32 {
813        let mut rst = 0;
814        let (mut xsum, mut nsum) = (i32::MIN, i32::MAX);
815
816        let mut pfx = 0;
817        for n in nums {
818            pfx += n;
819
820            xsum = xsum.max(pfx);
821            nsum = nsum.min(pfx);
822
823            use std::cmp::Ordering::*;
824            match pfx.cmp(&0) {
825                Greater => rst = rst.max(pfx.max(pfx - nsum)),
826                Less => rst = rst.max((-pfx).max(xsum - pfx)),
827                _ => (),
828            }
829        }
830
831        rst
832    }
833}
834
835/// 1751h Maximum Number of Events That Can Be Attended
836struct Sol1751 {}
837
838impl Sol1751 {
839    pub fn max_values(mut events: Vec<Vec<i32>>, k: i32) -> i32 {
840        events.sort_by_key(|v| v[0]);
841        println!("-> {events:?}");
842
843        let rsearch = |target| {
844            let (mut l, mut r) = (0, events.len());
845            while l < r {
846                let m = l + ((r - l) >> 1);
847                if events[m][0] <= target {
848                    l = m + 1;
849                } else {
850                    r = m;
851                }
852            }
853
854            l
855        };
856
857        let mut dp = vec![vec![0; events.len() + 1]; 1 + k as usize];
858        for start in (0..events.len()).rev() {
859            let x = rsearch(events[start][1]);
860            for k in 1..=k as usize {
861                dp[k][start] = (dp[k][start + 1]).max(dp[k - 1][x] + events[start][2]);
862            }
863        }
864
865        dp[k as usize][0]
866    }
867}
868
869/// 1857h Largest Color Value in a Directed Graph
870struct Sol1857 {}
871
872impl Sol1857 {
873    /// 1 <= V <= 10^5
874    /// 0 <= E <= 10^5
875    pub fn largest_path_value(colors: String, edges: Vec<Vec<i32>>) -> i32 {
876        use std::collections::{HashMap, HashSet};
877
878        let mut gadj: HashMap<usize, HashSet<usize>> = HashMap::new();
879        for edge in edges.iter() {
880            gadj.entry(edge[0] as usize)
881                .or_default()
882                .insert(edge[1] as usize);
883        }
884        println!("-> {gadj:?}");
885
886        let colors = colors.as_bytes();
887        let mut dp = vec![[0; 26]; colors.len()];
888
889        #[derive(Clone, PartialEq, Debug)]
890        enum OpColor {
891            NotVisited, // White
892            Visiting,   // Gray
893            Visited,    // Black
894        }
895
896        fn search(
897            v: usize,
898            dp: &mut [[usize; 26]],
899            colors: &[u8],
900            gadj: &HashMap<usize, HashSet<usize>>,
901            coloring: &mut [OpColor],
902        ) -> bool {
903            if coloring[v] != OpColor::NotVisited {
904                return true;
905            }
906
907            coloring[v] = OpColor::Visiting;
908
909            if let Some(uset) = gadj.get(&v) {
910                for &u in uset.iter() {
911                    match coloring[u] {
912                        OpColor::Visited => {}
913                        OpColor::Visiting => return true,
914                        OpColor::NotVisited => {
915                            if search(u, dp, colors, gadj, coloring) {
916                                return true;
917                            }
918                        }
919                    }
920
921                    for color in 0..26 {
922                        dp[v][color] = dp[v][color].max(dp[u][color]);
923                    }
924                }
925            }
926
927            dp[v][(colors[v] - b'a') as usize] += 1;
928
929            coloring[v] = OpColor::Visited;
930            false
931        }
932
933        let mut coloring = vec![OpColor::NotVisited; colors.len()];
934        for src in 0..colors.len() {
935            if coloring[src] == OpColor::NotVisited
936                && search(src, &mut dp, colors, &gadj, &mut coloring)
937            {
938                return -1;
939            }
940        }
941
942        println!("-> {dp:?}");
943
944        match dp
945            .iter()
946            .map(|row| match row.iter().max() {
947                Some(&xrow) => xrow,
948                _ => 0,
949            })
950            .max()
951        {
952            Some(xgraph) => xgraph as i32,
953            _ => 0,
954        }
955    }
956}
957
958/// 1931h Painting a Grid With Three Different Colors
959struct Sol1931;
960
961impl Sol1931 {
962    /// 1 <= m <= 5, 1 <= n <= 1000
963    pub fn color_the_grid(m: i32, n: i32) -> i32 {
964        use std::collections::HashMap;
965
966        let mut masks = HashMap::new();
967        (0..3i32.pow(m as u32)).for_each(|mask| {
968            let mut colors = vec![];
969
970            let mut v = mask;
971            for _ in 0..m {
972                colors.push(v % 3);
973                v /= 3;
974            }
975
976            if !colors.windows(2).any(|w| w[0] == w[1]) {
977                masks.insert(mask, colors);
978            }
979        });
980
981        println!("-> Color Masks: {masks:?}");
982
983        let mut adjacents = HashMap::new();
984        for (&mask1, color1) in &masks {
985            for (&mask2, color2) in &masks {
986                if !color1
987                    .iter()
988                    .zip(color2.iter())
989                    .any(|(color1, color2)| color1 == color2)
990                {
991                    adjacents.entry(mask1).or_insert(vec![]).push(mask2);
992                }
993            }
994        }
995
996        println!("-> Rows Adjacent: {adjacents:?}");
997
998        const M: i32 = 1_000_000_007;
999
1000        {
1001            let mut dp_cur = vec![0; [1, 3, 9, 27, 81, 243][m as usize]];
1002            for &mask in masks.keys() {
1003                dp_cur[mask as usize] = 1;
1004            }
1005            for _ in 1..n {
1006                let mut dp_next = vec![0; dp_cur.len()];
1007                for mask in 0..[1, 3, 9, 27, 81, 243][m as usize] {
1008                    if dp_cur[mask as usize] > 0
1009                        && let Some(adjacent) = adjacents.get(&mask)
1010                    {
1011                        dp_next[mask as usize] = adjacent
1012                            .iter()
1013                            .fold(0, |count, &mask| (count + dp_cur[mask as usize]) % M);
1014                    }
1015                }
1016                dp_cur = dp_next;
1017            }
1018            println!(":: {}", dp_cur.iter().fold(0, |count, &n| (count + n) % M));
1019        }
1020
1021        let mut dp_cur = HashMap::new();
1022        for &mask in masks.keys() {
1023            dp_cur.insert(mask, 1);
1024        }
1025        for _ in 1..n {
1026            let mut dp_next = HashMap::new();
1027            for &mask in dp_cur.keys() {
1028                if let Some(adjacent) = adjacents.get(&mask) {
1029                    dp_next.insert(
1030                        mask,
1031                        adjacent.iter().fold(0, |count, &mask| {
1032                            (count + dp_cur.get(&mask).unwrap_or(&0)) % M
1033                        }),
1034                    );
1035                }
1036            }
1037            dp_cur = dp_next;
1038        }
1039
1040        dp_cur.values().fold(0, |count, &n| (count + n) % M)
1041    }
1042}
1043
1044/// 2140m Solving Questions With Brainpower
1045struct Sol2140;
1046
1047impl Sol2140 {
1048    pub fn most_points(questions: Vec<Vec<i32>>) -> i64 {
1049        use std::cmp::Ordering::*;
1050
1051        let mut dp = vec![[0i64; 2]; questions.len() + 1];
1052
1053        for (i, q) in questions.iter().enumerate().rev() {
1054            println!("-> {:?}", (i, &q));
1055
1056            dp[i][0] = dp[i + 1][0].max(dp[i + 1][1]);
1057
1058            let [pts, skip] = q[..2] else { unreachable!() };
1059            let next = i + 1 + skip as usize;
1060
1061            dp[i][1] = pts as i64
1062                + match next.cmp(&questions.len()) {
1063                    Less => dp[next][0].max(dp[next][1]),
1064                    _ => 0,
1065                };
1066
1067            println!("-> {:?}", dp);
1068        }
1069
1070        println!(":: {:?}", dp[0]);
1071
1072        dp[0][0].max(dp[0][1])
1073    }
1074
1075    /// Recursion with Memo
1076    fn recursive(questions: Vec<Vec<i32>>) -> i64 {
1077        let mut mem = vec![0; questions.len()];
1078
1079        fn search(i: usize, questions: &[Vec<i32>], mem: &mut [i64]) -> i64 {
1080            if i >= questions.len() {
1081                return 0;
1082            }
1083
1084            if mem[i] > 0 {
1085                return mem[i];
1086            }
1087
1088            let [pts, skip] = questions[i][..] else {
1089                unreachable!()
1090            };
1091            mem[i] = search(i + 1, questions, mem)
1092                .max(pts as i64 + search(i + 1 + skip as usize, questions, mem));
1093
1094            mem[i]
1095        }
1096
1097        let pts = search(0, &questions, &mut mem);
1098        println!("-> Mem: {:?}", mem);
1099
1100        pts
1101    }
1102}
1103
1104/// 2163h Minimum Difference in Sums After Removal of Elements
1105struct Sol2163 {}
1106
1107impl Sol2163 {
1108    pub fn minimum_difference(nums: Vec<i32>) -> i64 {
1109        use std::cmp::Reverse;
1110        use std::collections::BinaryHeap;
1111
1112        let n = nums.len() / 3;
1113        let mut part1 = vec![0i64; n + 1];
1114        let mut sum = 0i64;
1115
1116        let mut ql = BinaryHeap::new();
1117        for &v in nums.iter().take(n) {
1118            sum += v as i64;
1119            ql.push(v);
1120        }
1121
1122        part1[0] = sum;
1123        for i in n..2 * n {
1124            sum += nums[i] as i64;
1125            ql.push(nums[i]);
1126            sum -= ql.pop().unwrap() as i64;
1127            part1[i - (n - 1)] = sum;
1128        }
1129
1130        let mut part2 = 0i64;
1131
1132        let mut qr = BinaryHeap::new();
1133        for i in (2 * n..3 * n).rev() {
1134            part2 += nums[i] as i64;
1135            qr.push(Reverse(nums[i]));
1136        }
1137
1138        let mut m_diff = part1[n] - part2;
1139        for i in (n..2 * n).rev() {
1140            part2 += nums[i] as i64;
1141            qr.push(Reverse(nums[i]));
1142            if let Some(Reverse(val)) = qr.pop() {
1143                part2 -= val as i64;
1144            }
1145            m_diff = m_diff.min(part1[i - n] - part2);
1146        }
1147
1148        m_diff
1149    }
1150}
1151
1152/// 2787m Ways to Express an Integer as Sum of Powers
1153struct Sol2787 {}
1154
1155impl Sol2787 {
1156    pub fn number_of_ways(n: i32, x: i32) -> i32 {
1157        const M: i64 = 1e9 as i64 + 7;
1158
1159        let n = n as usize;
1160        let mut ks = vec![vec![0; n + 1]; n + 1]; // Knapsack
1161
1162        let items: Vec<_> = (0..=n).map(|p| (p as i64).pow(x as u32)).collect();
1163        println!("-> {items:?}");
1164
1165        ks[0][0] = 1;
1166        for item in 1..=n {
1167            let power = items[item] as usize;
1168            for capacity in 0..=n {
1169                ks[item][capacity] = ks[item - 1][capacity];
1170                if power <= capacity {
1171                    ks[item][capacity] = (ks[item][capacity] + ks[item - 1][capacity - power]) % M
1172                }
1173            }
1174        }
1175
1176        println!("-> {ks:?}");
1177
1178        ks[n][n] as _
1179    }
1180}
1181
1182/// 2836h Maximize Value of Function in a Ball Passing Game
1183struct Sol2836;
1184
1185impl Sol2836 {
1186    pub fn get_max_function_value(receiver: Vec<i32>, k: i64) -> i64 {
1187        // Binary Lifting
1188        // far(p, i) :: 2^p ancestor of i
1189        // far(p, i) = far(p-1, far(p-1, i))
1190
1191        println!(" || {:?}", receiver);
1192
1193        let (bits, nodes) = (k.ilog2() as usize + 1, receiver.len());
1194
1195        let mut far = vec![vec![0; bits]; nodes];
1196        (0..bits).for_each(|p| {
1197            (0..nodes).for_each(|i| match p {
1198                0 => far[i][0] = receiver[i] as usize,
1199                _ => far[i][p] = far[far[i][p - 1]][p - 1],
1200            })
1201        });
1202
1203        println!(" -> {:?}", far);
1204
1205        let mut score = vec![vec![0i64; bits]; nodes];
1206        (0..bits).for_each(|p| {
1207            (0..nodes).for_each(|i| match p {
1208                0 => score[i][0] = receiver[i] as i64,
1209                _ => score[i][p] = score[i][p - 1] + score[far[i][p - 1]][p - 1],
1210            })
1211        });
1212
1213        println!(" -> {:?}", score);
1214
1215        (0..nodes).fold(0, |xscore, istart| {
1216            xscore.max({
1217                let (mut iscore, mut i) = (0, istart);
1218                (0..bits).rev().for_each(|p| {
1219                    if (1 << p) & k != 0 {
1220                        iscore += score[i][p];
1221                        i = far[i][p];
1222                    }
1223                });
1224                iscore + istart as i64
1225            })
1226        })
1227    }
1228}
1229
1230/// 2901m Longest Unequal Adjacent Groups Subsequence II
1231struct Sol2901;
1232
1233impl Sol2901 {
1234    pub fn get_words_in_longest_subsequence(words: Vec<String>, groups: Vec<i32>) -> Vec<String> {
1235        let mut dists = vec![vec![]; groups.len()];
1236        for (i, x) in words.iter().enumerate() {
1237            for y in words.iter().take(i) {
1238                dists[i].push(if x.len() != y.len() {
1239                    0
1240                } else {
1241                    x.chars()
1242                        .zip(y.chars())
1243                        .fold(0, |d, (x, y)| if x == y { d } else { d + 1 })
1244                });
1245            }
1246            dists[i].push(0);
1247        }
1248
1249        println!("-> {dists:?}");
1250
1251        fn valid_distance(x: &str, y: &str) -> bool {
1252            use std::cmp::Ordering::Equal;
1253            match x.len().cmp(&y.len()) {
1254                Equal => {
1255                    x.chars()
1256                        .zip(y.chars())
1257                        .filter(|(x, y)| x != y)
1258                        .collect::<Vec<_>>()
1259                        .len()
1260                        == 1
1261                }
1262                _ => false,
1263            }
1264        }
1265
1266        let mut picks = vec![usize::MAX; groups.len()];
1267        let mut longest = vec![1; groups.len()];
1268
1269        let (mut lmax, mut ilast) = (1, 0);
1270
1271        for i in 1..groups.len() {
1272            for j in 0..i {
1273                if groups[j] != groups[i]
1274                    && (dists[i][j] == 1 && valid_distance(&words[i], &words[j]))
1275                    && longest[i] < longest[j] + 1
1276                {
1277                    longest[i] = longest[j] + 1;
1278                    picks[i] = j;
1279                }
1280            }
1281
1282            if longest[i] > lmax {
1283                (lmax, ilast) = (longest[i], i);
1284            }
1285        }
1286
1287        println!("-> {lmax} | {longest:?}");
1288        println!("-> {ilast} | {picks:?}");
1289
1290        let mut lss = vec![];
1291        while ilast != usize::MAX {
1292            lss.push(words[ilast].to_owned());
1293            ilast = picks[ilast];
1294        }
1295        lss.reverse();
1296
1297        lss
1298    }
1299}
1300
1301/// 2999h Count the Number of Powerful Integers
1302struct Sol2999;
1303
1304impl Sol2999 {
1305    pub fn number_of_powerful_int(start: i64, finish: i64, limit: i32, s: String) -> i64 {
1306        let finish = finish.to_string();
1307        let start = format!("{:0>width$}", start.to_string(), width = finish.len());
1308
1309        println!("-> {:?}", (&start, &finish, limit, &s));
1310
1311        let mut mem = vec![-1; finish.len()];
1312
1313        fn search(
1314            i: usize,
1315            slimit: bool,
1316            start: &[u8],
1317            flimit: bool,
1318            finish: &[u8],
1319            limit: u8,
1320            s: &[u8],
1321            mem: &mut [i64],
1322        ) -> i64 {
1323            println!("-> {:?}", (i, slimit, flimit));
1324
1325            if i == (start.len() & finish.len()) {
1326                return 1;
1327            }
1328            if !slimit && !flimit && mem[i] != -1 {
1329                return mem[i];
1330            }
1331
1332            let mut count = 0;
1333            let sdigit = if slimit { start[i] } else { b'0' };
1334            let fdigit = if flimit { finish[i] } else { b'9' };
1335
1336            if i < finish.len() - s.len() {
1337                for digit in sdigit..=fdigit.min(limit) {
1338                    count += search(
1339                        i + 1,
1340                        slimit && digit == start[i],
1341                        start,
1342                        flimit && digit == finish[i],
1343                        finish,
1344                        limit,
1345                        s,
1346                        mem,
1347                    );
1348                }
1349            } else {
1350                let digit = s[i - (finish.len() - s.len())];
1351                if sdigit <= digit && digit <= fdigit.min(limit) {
1352                    count += search(
1353                        i + 1,
1354                        slimit && digit == start[i],
1355                        start,
1356                        flimit && digit == finish[i],
1357                        finish,
1358                        limit,
1359                        s,
1360                        mem,
1361                    );
1362                }
1363            }
1364
1365            if !slimit && !flimit {
1366                mem[i] = count;
1367            }
1368            count
1369        }
1370
1371        search(
1372            0,
1373            true,
1374            start.as_bytes(),
1375            true,
1376            finish.as_bytes(),
1377            b'0' + limit as u8,
1378            s.as_bytes(),
1379            &mut mem,
1380        )
1381    }
1382}
1383
1384/// 3068h Find the Maximum Sum of Node Values
1385struct Sol3068 {}
1386
1387impl Sol3068 {
1388    pub fn maximum_value_sum(nums: Vec<i32>, k: i32, edges: Vec<Vec<i32>>) -> i64 {
1389        println!("-> {edges:?}");
1390
1391        fn recursive(
1392            start: usize,
1393            xors: usize,
1394            nums: &[i32],
1395            k: i32,
1396            memo: &mut [[i64; 2]],
1397        ) -> i64 {
1398            if start == nums.len() {
1399                return match xors & 1 {
1400                    0 => 0,
1401                    _ => i64::MIN,
1402                };
1403            }
1404
1405            if memo[start][xors] != -1 {
1406                return memo[start][xors];
1407            }
1408
1409            let xsum = (nums[start] as i64 + recursive(start + 1, xors, nums, k, memo))
1410                .max((nums[start] ^ k) as i64 + recursive(start + 1, xors ^ 1, nums, k, memo));
1411            memo[start][xors] = xsum;
1412            xsum
1413        }
1414
1415        let mut memo = vec![[-1, -1]; nums.len()];
1416        println!(":: {}", recursive(0, 0, &nums, k, &mut memo));
1417
1418        let tabulation = || {
1419            let mut dp = vec![[-1, -1]; nums.len() + 1];
1420            (dp[nums.len()][0], dp[nums.len()][1]) = (0, i64::MIN);
1421
1422            for i in (0..nums.len()).rev() {
1423                for xor in [0, 1] {
1424                    dp[i][xor] = (dp[i + 1][xor] + nums[i] as i64)
1425                        .max(dp[i + 1][xor ^ 1] + (nums[i] ^ k) as i64);
1426                }
1427            }
1428
1429            dp[0][0]
1430        };
1431        println!(":: {}", tabulation());
1432
1433        let mut changes: Vec<_> = nums.iter().map(|&n| (n ^ k) - n).collect();
1434        changes.sort_unstable_by_key(|&n| std::cmp::Reverse(n));
1435
1436        changes
1437            .chunks(2)
1438            .take_while(|chunk| chunk.len() == 2)
1439            .inspect(|chunk| println!("-> {chunk:?}"))
1440            .map(|v| (v[0] + v[1]) as i64)
1441            .take_while(|&diff| diff > 0)
1442            .sum::<i64>()
1443            + nums.iter().map(|&n| n as i64).sum::<i64>()
1444    }
1445}
1446
1447/// 3333h Find the Original Typed String II
1448struct Sol3333 {}
1449
1450impl Sol3333 {
1451    /// 1 <= N <= 10^5
1452    /// 1 <= k <= 2000
1453    pub fn possible_string_count(word: String, k: i32) -> i32 {
1454        let mut f = 1;
1455        let mut freqs = word
1456            .chars()
1457            .collect::<Vec<_>>()
1458            .windows(2)
1459            .fold(vec![], |mut freqs, w| {
1460                if w[0] == w[1] {
1461                    f += 1;
1462                } else {
1463                    freqs.push(f);
1464                    f = 1;
1465                }
1466                freqs
1467            });
1468        freqs.push(f);
1469        println!("-> {freqs:?}");
1470
1471        const M: i64 = 1e9 as i64 + 7;
1472
1473        let k = k as usize;
1474        let total = freqs.iter().fold(1, |total, &f| f * total % M);
1475        if freqs.len() >= k {
1476            return total as _;
1477        }
1478
1479        let mut counts = vec![vec![0; k]; freqs.len() + 1];
1480        counts[0][0] = 1;
1481
1482        for g in 0..freqs.len() {
1483            for l in 1..k {
1484                for x in 1..=freqs[g] as usize {
1485                    if l >= x {
1486                        counts[g + 1][l] = (counts[g + 1][l] + counts[g][l - x]) % M;
1487                    }
1488                }
1489            }
1490        }
1491
1492        counts
1493            .last()
1494            .unwrap()
1495            .iter()
1496            .fold(total, |total, &count| (total - count + M) % M) as _
1497    }
1498}
1499
1500/// 3335m Total Characters in String After Transformations I
1501struct Sol3335;
1502
1503impl Sol3335 {
1504    /// 1 <= N, t <= 10^5
1505    pub fn length_after_transformations(s: String, t: i32) -> i32 {
1506        const M: i32 = 1e9 as i32 + 7;
1507
1508        let mut freqs = vec![vec![0; 26]; t as usize + 1];
1509        for chr in s.as_bytes() {
1510            freqs[0][(chr - b'a') as usize] += 1;
1511        }
1512
1513        for i in 1..=t as usize {
1514            freqs[i][0] = freqs[i - 1][25];
1515            freqs[i][1] = (freqs[i - 1][0] + freqs[i - 1][25]) % M;
1516            for chr in 2..26 {
1517                freqs[i][chr] = freqs[i - 1][chr - 1]
1518            }
1519        }
1520
1521        println!("-> {freqs:?}");
1522
1523        freqs[t as usize].iter().fold(0, |t, &l| (t + l) % M)
1524    }
1525}
1526
1527/// 3337m Total Characters in String After Transformations II
1528struct Sol3337;
1529
1530impl Sol3337 {
1531    /// 1 <= N <= 10^5, 1 <= t <= 10^9
1532    pub fn length_after_transformations(s: String, t: i32, nums: Vec<i32>) -> i32 {
1533        // M a b c d e f g ... y z
1534        // a   1 1                 / N_a: 2
1535        // b     1 1 1             / N_b: 3
1536        // c       1               / N_c: 1
1537        // ...
1538        // y 1                   1 / N_y: 2
1539        // z 1 1 1 1               / N_z: 4
1540
1541        type M = [[i64; 26]; 26];
1542
1543        let mut m: M = [[0; 26]; 26];
1544        for chr in 0..26 {
1545            for t in 1..=nums[chr] as usize {
1546                m[chr][(chr + t) % 26] = 1;
1547            }
1548        }
1549
1550        let mut freq = [0; 26];
1551        for chr in s.as_bytes() {
1552            freq[(chr - b'a') as usize] += 1;
1553        }
1554
1555        const MOD: i64 = 1e9 as i64 + 7;
1556
1557        fn mcopy(t: &mut M, f: &M) {
1558            for i in 0..26 {
1559                for j in 0..26 {
1560                    t[i][j] = f[i][j];
1561                }
1562            }
1563        }
1564
1565        fn mzero(m: &mut M) {
1566            for row in m.iter_mut() {
1567                for v in row.iter_mut() {
1568                    *v = 0;
1569                }
1570            }
1571        }
1572
1573        fn matrix_multiply(m: &mut M, a: &M, b: &M) {
1574            mzero(m);
1575
1576            for i in 0..26 {
1577                for (k, b_k) in b.iter().enumerate() {
1578                    let a_ik = a[i][k];
1579                    if a_ik != 0 {
1580                        for (j, b_k_j) in b_k.iter().enumerate() {
1581                            m[i][j] = (m[i][j] + a_ik * b_k_j) % MOD;
1582                        }
1583                    }
1584                }
1585            }
1586        }
1587
1588        /// <- b^e
1589        fn square_exponentiation(b: &M, mut e: i32) -> M {
1590            let mut power: M = [[0; 26]; 26];
1591            for (d, row) in power.iter_mut().enumerate() {
1592                row[d] = 1;
1593            }
1594
1595            let mut base: M = [[0; 26]; 26];
1596            mcopy(&mut base, b);
1597
1598            let mut t: M = [[0; 26]; 26];
1599            while e > 0 {
1600                if e & 1 == 1 {
1601                    matrix_multiply(&mut t, &power, &base);
1602                    mcopy(&mut power, &t);
1603                }
1604
1605                matrix_multiply(&mut t, &base, &base);
1606                mcopy(&mut base, &t);
1607
1608                e >>= 1;
1609            }
1610
1611            power
1612        }
1613
1614        let power: M = square_exponentiation(&m, t);
1615
1616        println!("-> M^t {power:?}");
1617
1618        let mut tfreq = [0; 26];
1619        for i in 0..26 {
1620            for j in 0..26 {
1621                tfreq[i] = (tfreq[i] + freq[i] * power[i][j]) % MOD;
1622            }
1623        }
1624
1625        println!("-> {tfreq:?}");
1626
1627        tfreq.iter().fold(0, |l, &n| (l + n) % MOD) as _
1628    }
1629}
1630
1631/// 3363h Find the Maximum Number of Fruits Collected
1632struct Sol3363 {}
1633
1634impl Sol3363 {
1635    pub fn max_collected_fruits(mut fruits: Vec<Vec<i32>>) -> i32 {
1636        fn walk(fruits: &[Vec<i32>]) -> i32 {
1637            let n = fruits.len();
1638            let mut prv = vec![i32::MIN; n];
1639            prv[n - 1] = fruits[0][n - 1];
1640
1641            let mut cur = vec![i32::MIN; n];
1642            for (r, fruits) in fruits.iter().enumerate().skip(1).take(fruits.len() - 2) {
1643                for c in (n - 1 - r).max(r + 1)..n {
1644                    let mut best = prv[c];
1645                    if c > 0 {
1646                        best = best.max(prv[c - 1]);
1647                    }
1648                    if c < n - 1 {
1649                        best = best.max(prv[c + 1]);
1650                    }
1651                    cur[c] = best + fruits[c];
1652                }
1653                (0..n).for_each(|i| prv[i] = cur[i]);
1654            }
1655
1656            prv[n - 1]
1657        }
1658
1659        let mut xcolls = (0..fruits.len()).map(|d| fruits[d][d]).sum();
1660        xcolls += walk(&fruits);
1661        for r in 0..fruits.len() {
1662            for c in 0..r {
1663                (fruits[r][c], fruits[c][r]) = (fruits[c][r], fruits[r][c]);
1664            }
1665        }
1666        xcolls += walk(&fruits);
1667
1668        xcolls
1669    }
1670}
1671
1672/// 3459h Length of Longest V-Shaped Diagonal Segment
1673struct Sol3459 {}
1674
1675impl Sol3459 {
1676    pub fn len_of_v_diagonal(grid: Vec<Vec<i32>>) -> i32 {
1677        use std::collections::HashMap;
1678
1679        const DIRS: [(isize, isize); 4] = [(1, 1), (1, -1), (-1, -1), (-1, 1)];
1680        let mut cache: HashMap<(usize, usize, usize, bool), i32> = HashMap::new();
1681
1682        fn search(
1683            grid: &[Vec<i32>],
1684            y: usize,
1685            x: usize,
1686            dir: usize,
1687            turned: bool,
1688            target: i32,
1689            cache: &mut HashMap<(usize, usize, usize, bool), i32>,
1690        ) -> i32 {
1691            let (r, c) = (
1692                y.wrapping_add_signed(DIRS[dir].0),
1693                x.wrapping_add_signed(DIRS[dir].1),
1694            );
1695
1696            if r >= grid.len() || c >= grid[0].len() || grid[r][c] != target {
1697                return 0;
1698            }
1699
1700            if let Some(&steps) = cache.get(&(r, c, dir, turned)) {
1701                return steps;
1702            }
1703
1704            let mut steps = search(grid, r, c, dir, turned, 2 - grid[r][c], cache);
1705            if !turned {
1706                steps = search(grid, r, c, (dir + 1) % 4, true, 2 - grid[r][c], cache).max(steps);
1707            }
1708            cache.insert((r, c, dir, turned), steps + 1);
1709
1710            println!("-> {cache:?}");
1711
1712            steps + 1
1713        }
1714
1715        grid.iter().enumerate().fold(0, |x_steps, (r, row)| {
1716            x_steps.max(
1717                row.iter()
1718                    .enumerate()
1719                    .filter_map(|(c, &g)| if g == 1 { Some(c) } else { None })
1720                    .map(|c| {
1721                        (0..4)
1722                            .map(|dir| search(&grid, r, c, dir, false, 2, &mut cache) + 1)
1723                            .max()
1724                            .unwrap_or(0)
1725                    })
1726                    .max()
1727                    .unwrap_or(0),
1728            )
1729        })
1730    }
1731}
1732
1733#[cfg(test)]
1734mod tests;