bzoj1090(SCOI2003)字符串折叠

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1090

像这种的一看就是区间dp。涉及合并什么的。

需要注意的是那个括号前的数字不一定是一位!

而且所有涉及区间的用的都是已经算好的dp值,比如那个折叠的地方,不是直接的长度,而是那一块的dp值!

不需要把dp想复杂。只要考虑设计了状态之后怎样转移。

  转移常常需要分类讨论,比如这里就分类一下该区间要不要整体折叠。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int dp[105][105],n;
char a[105];
int check(int l,int k,int r)
{
    int x=k-l,y=r-k+1;
    if(y%x)return 0;
    int s=y/x;
    for(int i=l;i<k;i++)
        for(int j=1;j<=s;j++)
            if(a[i+j*x]!=a[i])return 0;
    return 1;
}
int cal(int a)
{
    int ret=0;
    while(a)a/=10,ret++;
    return ret;
}
int main()
{
    cin>>(a+1);n=strlen(a+1);
    memset(dp,1,sizeof dp);
    for(int i=1;i<=n;i++)dp[i][i]=1;
    for(int d=2;d<=n;d++)
        for(int l=1;l<=n-d+1;l++)
        {
            int r=l+d-1;dp[l][r]=r-l+1;/////////
            for(int j=l;j<r;j++)
            {
                dp[l][r]=min(dp[l][r],dp[l][j]+dp[j+1][r]);
                if(check(l,j+1,r))dp[l][r]=min(dp[l][r],dp[l][j]+2+cal((r-l+1)/(j+1-l)));
                                                ///不是s,而是dp[l][j] 
            }
        }
    printf("%d",dp[1][n]);
    return 0;
}
原文地址:https://www.cnblogs.com/Narh/p/9147949.html