【upc】画 (picture) | 区间dp、思维转换

题目描述

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套路 ,遍历每一个分界点即可

Code:

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<e;j++)
                    dp[i][e] = min(dp[i][e],dp[i][j]+dp[j+1][e]);
            }
        }
        printf("%lld\n",dp[1][n]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43857314/article/details/107747080