BZOJ1068_压缩_KEY

题目传送门

区间DP,设f[i][j][0/1]为i~j区间的压缩情况,1表示在插入了一个M。

code:

/**************************************************************
    Problem: 1068
    User: yekehe
    Language: C++
    Result: Accepted
    Time:56 ms
    Memory:1308 kb
****************************************************************/
 
#include <cstdio>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
 
string S;
int f[51][51][2];
 
int check(int i,int j)
{
    int mid=i+j>>1;
    for(int k=0;k<=mid-i;k++)
        if(S[i+k]!=S[mid+1+k])return 0;
    return 1;
}
 
int main()
{
    cin>>S;
    int N=S.size();
        for(int i=N-1;i>=0;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][0]=min(f[i][j][0],f[i][k][0]+j-k);//不加M直接取
                for(int k=i;k<j;k++)
                    f[i][j][1]=min(min(f[i][k][0],f[i][k][1])+min(f[k+1][j][0],f[k+1][j][1])+1,f[i][j][1]);//加了M的情况枚举k在哪里加入M
                if(!((j-i+1)&1)&&check(i,j)){
                    f[i][j][0]=min(f[i][j][0],f[i][i+j>>1][0]+1);//这里之所以是0,是因为默认前段为起点,即默认有M存在。(类似于i~j区间为一个单独的串)
                }
                if(!(i^j))f[i][j][1]=N+1;//i==j
            }
    printf("%d",min(f[0][N-1][0],f[0][N-1][1]));
    return 0;
}

 

posted @ 2018-03-30 10:14  Cptraser  阅读(...)  评论(...编辑  收藏