bzoj 1068: [SCOI2007]压缩

/**************************************************************
    Problem: 1068
    User: lxy8584099
    Language: C++
    Result: Accepted
    Time:20 ms
    Memory:900 kb
****************************************************************/
 
/*
    胡乱DP
    hash
    f i,j,k 表示 i~j 有没有M的最小长度 
    默认在i-1处有一个M
    这样由子问题转到最后的问题 1-1即0处就存在一个M  
    这样操作不影响转移 
*/
#include<cstdio>
#include<cstring>
#define ll unsigned long long
using namespace std;
const int N=100;
ll B=233,base[N]={1},s[N];
char str[N];
int f[N][N][2],n;
int min(int a,int b) {return a>b?b:a;} 
ll hash(int l,int r)
{
    return s[r]-s[l-1]*base[r-l+1];
}
int main()
{
    memset(f,0x3f,sizeof(f));
    scanf("%s",str+1);
    n=strlen(str+1);
    for(int i=1;i<=n;i++)
    {
        base[i]=base[i-1]*B;
        s[i]=s[i-1]*B+str[i];
    }
    for(int i=n;i>=1;i--)
    for(int j=i;j<=n;j++)
    {
        f[i][j][0]=f[i][j][1]=j-i+1;
        for(int k=i;k<j;k++) 
            f[i][j][1]=min(f[i][j][1],
            min(f[i][k][0],f[i][k][1])+1 // 这个1是k+1 -1处 默认的 M 
            +min(f[k+1][j][1],f[k+1][j][0]));
        // 可能有的就是任何情况的最小值 
        for(int k=i;k<j;k++) f[i][j][0]=min(f[i][j][0],f[i][k][0]+j-k);
        // 这里不是 f[i][k][0]+f[k+1][j][0] 因为k往后走 一定能包括此方案 
        // 所以把后面的默认为一个一个 dou 起来的 
        // 不可能有的就只能由不可能转过来 
        int mid=(i+j)>>1;
        if((j-i+1)%2==0&&hash(i,mid)==hash(mid+1,j))
            f[i][j][0]=f[i][mid][0]+1; // 需要一个R 
        //能缩就缩  
    }
    printf("%d\n",min(f[1][n][0],f[1][n][1]));
     
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/lxy8584099/p/10313198.html
今日推荐