1. 程式人生 > >[SCOI2007]壓縮(洛谷P2470)

[SCOI2007]壓縮(洛谷P2470)

pac nbsp -s ace def define target span 表示

壓縮

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define MAXN 55
#define INF 0x3f3f3f3f
#define mid ((l+r)>>1)
int n,f[MAXN][MAXN][2];
//不妨處理每個子串時,我們都在它的前面放一個M,最後答案長度-1即可
//f[l][r][0]表示子串[l,r]中除了前面的M,串中還存在其他的M的最短長度
//f[l][r][1]則表示只有前面一個M的最短長度

/*
    三個轉移方程:
    1.if(該串左右兩半相同)
     f[l][r][1]=min(f[l][r][1],f[l][mid][1]+1);    壓縮與不壓縮
    2. i l~r-1 
        f[l][r][1]=min(f[l][r][1],f[l][i][1]+r-i);
    3. i l~r-1
        f[l][r][0]=min(f[l][r][0],min(f[l][i][0],f[l][i][1])+min(f[i+1][r][0],f[i+1][r][1]));
*/ char s[MAXN]; int dp(int l,int r,bool op){ if(f[l][r][op]) return f[l][r][op]; if(l==r) return f[l][r][op]=2; int &d=f[l][r][op]=r-l+2; if(op){ bool flag=1; if((r-l+1)%2==1) flag=0; if(flag) for(int i=l;i<=mid;i++) if(s[i]!=s[mid+i-l+1
]){ flag=0; break; } if(flag) d=min(d,dp(l,mid,1)+1); for(int i=l;i<r;i++) d=min(d,dp(l,i,1)+r-i); } else for(int i=l;i<r;i++) d=min(d,min(dp(l,i,0),dp(l,i,1))+min(dp(i+1,r,0),dp(i+1,r,1))); return d; } int main() { scanf("%s",s+1); n=strlen(s+1
); dp(1,n,0); dp(1,n,1); printf("%d\n",min(f[1][n][0],f[1][n][1])-1); return 0; }

[SCOI2007]壓縮(洛谷P2470)