bzoj 1068: [SCOI2007]压缩

本文通过一道具体的题目,介绍了一种使用区间DP方法解决的问题。文章详细解释了如何定义状态$f[i][j]$并给出了三种状态转移的方式。此外,还提供了一份完整的C++代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

做之前可以先做一下这题 http://www.lydsy.com/JudgeOnline/problem.php?id=1090

本来是想做一道区间DP的

然而太弱 并没有很快理解如何用传统区间DP(区间合并)来写这题

于是先用自己yy的比较水的方法做了一遍(其实也就是模拟题意中的压缩操作)

用$f[i][j]$表示 现在原串处理好了第$i$位 且缓冲串长度为$j$时的最小花费

那么$f[i][j]$可以从这三种情况转移过来

$f[i-1][j-1]+1$(填原字母)

$f[i-j/2][j/2]+1$(填R,j为偶数)

$f[i][k]+1$(填M,j=0)

于是这样就可以先水过(注意$j$的一个比较粗略的上界是$2i$)

#include <bits/stdc++.h>
using namespace std;
char s[60];
int f[60][110];
int n,ans;
bool check(int L,int R)
{
    int len=R-L+1;
    for(int i=L;i<=R;++i)
        if(s[i]!=s[i-len])
            return 0;
    return 1;
}
int main()
{
    memset(f,0x3f,sizeof(f));
    scanf("%s",&s[1]);
    n=strlen(&s[1]);
    f[0][0]=0;
    for(int i=1;i<=n;++i)
    {
        for(int j=max((i-1)*2,1);j;--j)
        {
            f[i][j]=f[i-1][j-1]+1;
            if((j&1)==0&&check(i-j/2+1,i))
                f[i][j]=min(f[i][j],f[i-j/2][j/2]+1);
            f[i][0]=min(f[i][0],f[i][j]+1);
        }
    }
    ans=f[n][0];
    for(int i=n*2;i;--i)
        ans=min(ans,f[n][i]);
    printf("%d\n",ans);
    return 0;
}

先把这个坑挖着 以后会了再来用传统区间DP方法来填坑

转载于:https://www.cnblogs.com/sagitta/p/4777297.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值