time limit per test : 3 seconds
memory limit per test : 256 megabytes
You are given a string
s
s
s of length
n
n
n consisting of lowercase Latin letters. You may apply some operations to this string: in one operation you can delete some contiguous substring of this string, if all letters in the substring you delete are equal. For example, after deleting substring
b
b
b
b
bbbb
bbbb from string
a
b
b
b
b
a
c
c
d
d
abbbbaccdd
abbbbaccdd we get the string
a
a
c
c
d
d
aaccdd
aaccdd.
Calculate the minimum number of operations to delete the whole string
s
s
s.
Input
The first line contains one integer
n
(
1
≤
n
≤
500
)
n(1≤n≤500)
n(1≤n≤500) — the length of string
s
s
s.
The second line contains the string
s
(
∣
s
∣
=
n
)
s(|s|=n)
s(∣s∣=n) consisting of lowercase Latin letters.
Output
Output a single integer — the minimal number of operation to delete string s s s .
题意:
给一个字符串,你每次操作可以删除一段连续的相同字符,例如字符串
a
b
b
b
b
a
c
c
d
d
abbbbaccdd
abbbbaccdd删去
b
b
b
b
bbbb
bbbb之后变成
a
c
c
d
d
accdd
accdd,请问至少操作多少次才会将这个字符串删没。
题解:
f
[
i
]
[
j
]
[
k
]
f[i][j][k]
f[i][j][k]表示为把
i
i
i到
j
j
j这个区间删到只剩下字母
k
k
k的最少操作。
f
[
i
]
[
j
]
[
a
]
=
m
i
n
(
f
[
i
]
[
j
]
[
a
]
,
f
[
i
]
[
k
]
[
a
]
+
f
[
k
+
1
]
[
j
]
[
b
]
+
(
a
!
=
b
)
)
f[i][j][a] = min(f[i][j][a],f[i][k][a]+f[k+1][j][b]+(a!=b))
f[i][j][a]=min(f[i][j][a],f[i][k][a]+f[k+1][j][b]+(a!=b))
这个算法复杂度是
O
(
(
n
3
)
∗
26
∗
26
)
O((n^3)*26*26)
O((n3)∗26∗26)
但是其实关于字母的状态数比较少,可以用map优化这个算法,将
f
[
i
]
[
j
]
f[i][j]
f[i][j]设为map,然后只要枚举存在的状态即可。
#include<bits/stdc++.h>
#define LiangJiaJun main
#define INF n+4
using namespace std;
int n;
map<int,int>f[504][504];
char s[504];
int LiangJiaJun(){
scanf("%d",&n);
scanf("%s",s+1);
for(int l=1;l<=n;l++){
for(int i=1;i+l-1<=n;i++){
int j=i+l-1;
if(l==1)f[i][j][s[i]-'a']=0;
for(int k=i;k<j;k++){
for(auto a:f[i][k]){
for(auto b:f[k+1][j]){
if(!f[i][j].count(a.first))f[i][j][a.first]=INF;
f[i][j][a.first]=min(f[i][j][a.first],(a.second)+(b.second)+((a.first)!=(b.first)));
}
}
}
}
}
int mint=INF;
for(int i=0;i<26;i++){
if(!f[1][n].count(i))continue;
mint=min(mint,f[1][n][i]);
}
printf("%d\n",mint+1);
return 0;
}