use std::io::{self, *};
fn main() {
let stdin = io::stdin();
unsafe {
for line in stdin.lock().lines() {
let ll = line.unwrap();
let numbers: Vec<&str> = ll.split(" ").collect();
let ans = min_add(numbers[0]);
print!("{}\n", ans);
}
}
}
fn min_add2(s: &str) -> i32 {
let sc: Vec<char> = s.chars().collect();
let mut stack: Vec<char> = vec![];
let mut ans = 0;
for c in sc.iter() {
if *c == ']' || *c == ')' {
loop {
if stack.len() == 0 {
ans += 1;
break;
}
if *c == ']' {
if stack[stack.len() - 1] == '[' {
stack.pop();
break;
}
ans += 1;
stack.pop();
} else if *c == ')' {
if stack[stack.len() - 1] == '(' {
stack.pop();
break;
}
ans += 1;
stack.pop();
}
}
} else if *c == '[' || *c == '(' {
stack.push(*c);
}
}
ans
}
fn min_add(s: &str) -> i32 {
let mut n = s.len() as i32;
let mut dp: Vec<Vec<i32>> = vec![];
for i in 0..n {
dp.push(vec![]);
for _ in 0..n {
dp[i as usize].push(-1);
}
}
return process(s, 0, s.len() as i32 - 1, &mut dp);
}
// 让s[l...r]都完美匹配
// 至少需要加几个字符
fn process(s: &str, l: i32, r: i32, dp: &mut Vec<Vec<i32>>) -> i32 {
// 只有一个字符,不管是什么,要想配对,都需要添加一个字符
if l == r {
return 1;
}
// 只有两个字符,
// 如果是()、[],那什么也不需要添加
// 否则,都需要添加2个字符
let sc: Vec<char> = s.chars().collect();
if l == r - 1 {
if (sc[l as usize] == '(' && sc[r as usize] == ')')
|| (sc[l as usize] == '[' && sc[r as usize] == ']')
{
return 0;
}
return 2;
}
if dp[l as usize][r as usize] != -1 {
return dp[l as usize][r as usize];
}
// 重点是如下的过程
// 可能性1,先搞定l+1...r,然后搞定l
// 比如s[l...r] = ([][]
// 先搞定[][],需要添加0个,然后搞定(,需要添加1个
// 整体变成([][])搞定
// l....r -> l l+1....r ?
let p1 = 1 + process(s, l + 1, r, dp);
// 可能性2,先搞定l...r-1,然后搞定r
// 和可能性1同理
// l...r -> ? l...r-1 r
let p2 = 1 + process(s, l, r - 1, dp);
// l( ...r) l+1..r-1
// l[ r] l+1..r-1
// 可能性3,s[l]和s[r]天然匹配,需要搞定的就是l+1..r-1
// 比如([[),搞定中间的[[,就是最优解了
let mut p3 = i32::MAX;
if (sc[l as usize] == '(' && sc[r as usize] == ')')
|| (sc[l as usize] == '[' && sc[r as usize] == ']')
{
p3 = process(s, l + 1, r - 1, dp);
}
// l......r
// l..l l+1..r
// l..l+1 l+2..r
// l...l+2 l+3..r
// 可能性后续:可能,最优解并不是l....r整体变成最大的嵌套
// 而是,并列关系!
// l....split 先变成合法
// split+1...r 再变成合法
// 是并列的关系!
// 比如(())[[]]
// l...split : (())
// split+1...r : [[]]
// 这种并列关系下,有可能出最优解
// 所以,枚举每一个可能的并列划分点(split)
let mut ans = get_min(p1, get_min(p2, p3));
for split in l..r {
ans = get_min(ans, process(s, l, split, dp) + process(s, split + 1, r, dp));
}
dp[l as usize][r as usize] = ans;
return ans;
}
fn get_min<T: Clone + Copy + std::cmp::PartialOrd>(a: T, b: T) -> T {
if a < b {
a
} else {
b
}
}
经过测试用栈是不行的

京公网安备 11010502036488号