BZOJ 1068 [SCOI2007]压缩 区间DP

题意:链接

方法:区间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 110
using 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));
}

你可能感兴趣的:(压缩,代码,dp,markdown)