题目描述
licunchun 找到了一张画。
licunchun 学习了膜法,想要一块一块地,让里面的颜色消失。
照片的颜色只有一行。licunchun 每次可以选择中间一段相同颜色的一段直接让它消失。
licunchun 想知道所需要的最少次数。
licunchun 冥思苦想了1145141919810都没有想出来,于是把问题交给了你。
输入
第一行输入T,表示数据组数
对于每组数据:
第一行给定一个n,表示照片的长度。
第二行,给定一串s,用来描述这个照片的颜色。为了方便,颜色的描述统一用小写字母,一种字母表示一种颜色。
输出
对于每组数据T,一行输出一个数字,表示所需要的最少次数。
样例输入 Copy
3 5 abaca 8 abcddcba 7 lggmmro
样例输出 Copy
3 4 5
提示
中文题意
应该都会想到区间dp
主要是怎么考虑的问题
一般来说,区间dp都是从终点状态出发,倒推
那么显然dp[i][i] = 1
现在考虑一个非常重要的性质:
一个区间按照题目给的规律删除完之后,边界的数一定可以保证是最后一个被删除
简单证明一下:
如果边界的数在区间中出现一次,那么绝对最后一个删除
如果区间中存在边界上的数,那么最优情况是两者之一:
1.先删除多余的数,最后一起删除边界数
2.先删除边界的数,最后在删除多余的数,显然最边上的边界的数,并不影响多余的数,所以此时删除边界的数还是可以作为最后一个删除
有了这个性质,区间dp就很容易解出了
当s[i] == s[j]时,显然s[j] 可以和s[i,j-1]一起删除,根据上述性质,同理可得 s[i] 可以 和s[i+1,j]一起删除
之后就是普通的区间dp套路 ,遍历每一个分界点即可
ll n,m,p;
char s[maxn];
ll dp[505][505];
int main()
{
int T;scanf("%d",&T);
while(T--){
read(n);
scanf("%s",s+1);
for(int i=1;i<=n;i++) dp[i][i] = 1;
for(int l=1;l<=n;l++){
for(int i=1;i+l<=n;i++){
int e = i+l;
dp[i][e] = INF;
if(s[i] == s[e]) dp[i][e] = min(dp[i][e],min(dp[i][e-1],dp[i+1][e]));
for(int j=i;j