BZOJ 1068 [SCOI2007]压缩 区间DP

来源:互联网 发布:天猫打印发货单软件 编辑:程序博客网 时间:2024/05/21 10:07

题意:链接

方法:区间DP

解析:

MD写题解(吐槽)写到一半markdown挂了什么鬼!

要不要这样!你知道我的内心是什么样的吗!

吐槽,啊呸,写题解写到一半突然丢失了我的内心是崩溃的好吗!


来我们重新写题解(吐槽)

这道题我刚开始列了个瞎(和谐)动规(二维的裸区间)

加上乱七八糟的判断是否有M后,居然有交叉!

一定是我逻辑错误,对就是这样!

后来又是一顿瞎(和谐)搞之后,代码抽的爆炸,然后我一测,c-free挂掉- -

过了一个小时后,我选择死亡。

然后看了一眼hzw的题解。

看到那个三维之后,我的内心直接崩溃,我脑子绝对被驴踢了我想不到开个三维?然后这之后的判断很简单啊!!

说正经的f[i][j][k]

k=1表示可以有M

k=0表示没有M

然后转移是这样的,类似1090那道题,枚举断点,

k=1时枚举断点递归更新,然后再设无断点更新,然后再判断是否自身能分为两个相等的串。

k=0时无断点更新,然后再判断是否自身能分为两个相等的串。

之后直接水过

代码:

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define N 110using namespace std;bool col[N][N][2];int f[N][N][2];char s[N];void init(){    memset(f,0x3f,sizeof(f));}int calc(int l,int r,int way){    if(l==r)return 1;    if(col[l][r][way])return f[l][r][way];    col[l][r][way]=1;    int len=r-l+1;    if(way)    {        for(int i=l;i<r;i++)        {            int tmp1=calc(l,i,1),tmp2=calc(i+1,r,1);            f[l][r][way]=min(f[l][r][way],tmp1+tmp2+1);        }    }    for(int i=l;i<r;i++)    {        int tmp1=calc(l,i,0),tmp2=r-i;        f[l][r][way]=min(f[l][r][way],tmp1+tmp2);    }    int ll=l,rr=r;    int lenlen=(rr-ll+1)/2;    int flag=1,mid;    if(!((rr-ll+1)&1))    {        mid=(ll+rr)>>1;        for(int i=ll;i<=mid;i++)        {            if(s[i]!=s[i+lenlen]){flag=0;break;}        }    }else flag=0;    if(flag)    {        int tmp=calc(l,mid,0);        f[l][r][way]=min(f[l][r][way],tmp+1);    }    return f[l][r][way];}int main(){    scanf("%s",s+1);    int len=strlen(s+1);    init();    printf("%d\n",calc(1,len,1));}
0 0