Solution#
Memo#
- 전형적인 백트래킹 + 가짓수를 줄여주는 메모이제이션 사용
// Baekjoon - 1342
// https://www.acmicpc.net/problem/1342
use std::{
collections::HashMap,
io::{self, Read, Write},
};
fn get_happy_num_count(
len: usize,
tmp_len: usize,
last_char: Option<usize>,
counts: &mut [i32; 26],
memo: &mut HashMap<(usize, Option<usize>, [i32; 26]), i32>,
) -> i32 {
if tmp_len == len {
return 1;
}
let key = (tmp_len, last_char, *counts);
if let Some(&cached) = memo.get(&key) {
return cached;
}
let mut result = 0;
for i in 0..26 {
if counts[i] > 0 && Some(i) != last_char {
counts[i] -= 1;
result += get_happy_num_count(len, tmp_len + 1, Some(i), counts, memo);
counts[i] += 1;
}
}
memo.insert(key, result);
result
}
fn main() {
let mut stdin = io::stdin().lock();
let mut stdout = io::stdout().lock();
let mut input = String::new();
stdin.read_to_string(&mut input).unwrap();
let input_line = input.lines().next().unwrap().trim();
let len = input_line.len();
let mut counts = [0i32; 26];
for c in input_line.chars() {
counts[c as usize - 'a' as usize] += 1;
}
let mut memo = HashMap::new();
let count = get_happy_num_count(len, 0, None, &mut counts, &mut memo);
writeln!(stdout, "{}", count).unwrap();
}
경로 1:
- 'a' 선택 → (tmp_len=1, last_char=Some(0), counts=[2,2,1,0,...,0])
- 'b' 선택 → (tmp_len=2, last_char=Some(1), counts=[2,1,1,0,...,0])
- 'c' 선택 → (tmp_len=3, last_char=Some(2), counts=[2,1,0,0,...,0])
- 'a' 선택 → (tmp_len=4, last_char=Some(0), counts=[1,1,0,0,...,0])
- 'b' 선택 → (tmp_len=5, last_char=Some(1), counts=[1,0,0,0,...,0])
- 'a' 선택 → 완성된 문자열 "abcaba"
경로 2:
- 'b' 선택 → (tmp_len=1, last_char=Some(1), counts=[3,1,1,0,...,0])
- 'a' 선택 → (tmp_len=2, last_char=Some(0), counts=[2,1,1,0,...,0])
- 'c' 선택 → (tmp_len=3, last_char=Some(2), counts=[2,1,0,0,...,0])
- 'a' 선택 → (tmp_len=4, last_char=Some(0), counts=[1,1,0,0,...,0])
- 'b' 선택 → (tmp_len=5, last_char=Some(1), counts=[1,0,0,0,...,0])
- 'a' 선택 → 완성된 문자열 "bacaba"
- 메모이제이션이 동작하는 예제는 위와 같다.
- abc, bac -> 같은 원소를 사용하고, 마지막문자가 같다면, 나머지로 만들어낼 수 있는 가짓수는 같다.
- 메모이제이션을 넣지 않은 러스트 풀이가 600ms대라서 찝찝해서 메모이제이션 했는데, 0ms가 나왔다.
- 참고로 동일한 메모이제이션 넣은 코틀린 풀이가 150ms대였는데, 미묘한 것 같다.