[BZOJ1068/Luogu2470][SCOI2007]压缩

BZOJ1068

Luogu2470

$f_{[l][r]}$

$f_{[l][r][0]}=\min_{i=l}^{r-1}\{f_{[l][i][0]}+r-i\}$

$f_{[l][r][0]}=f_{[l][(l+r)>>1][0]}+1$

$f_{[l][r][1]}=\min_{l=i}^{r-1}\{\min(f_{[l][i][0]},f_{[l][i][1]})+\min(f_{[i+1][r][0]},f_{[i+1][r][1]})\}$

#include <cstdio>
#include <cstring>

inline int Min(int a,int b){return a<b?a:b;}

int n,f[55][55][2];
char s[55];

inline bool Dou(int l,int r)//判断区间[l,r]是否是两个相同子串相连
{
if((r-l+1)&1)return false;
for(int i=l,j=(l+r+1)>>1;j<=r;++i,++j)
if(s[i]!=s[j])return false;
return true;
}

int DP(int l,int r,int m)
{
if(f[l][r][m])return f[l][r][m];
if(l==r)return f[l][r][m]=2;
int Res=0x3f3f3f3f;
if(!m)
{
if(Dou(l,r))Res=Min(Res,DP(l,(l+r)>>1,0)+1);
for(int i=l;i<r;++i)Res=Min(Res,DP(l,i,0)+r-i);
}
else
for(int i=l;i<r;++i)
Res=Min(Res,Min(DP(l,i,0),DP(l,i,1))+Min(DP(i+1,r,0),DP(i+1,r,1)));
return f[l][r][m]=Res;
}

int main()
{
scanf("%s",s+1),n=strlen(s+1);
printf("%d\n",Min(DP(1,n,0),DP(1,n,1))-1);
return 0;
}

posted @ 2018-12-29 21:06  LanrTabe  阅读(69)  评论(0编辑  收藏