bzoj 1068: [SCOI2007]压缩【区间dp】

神区间dp

设f[l][r][0]为在l到r中压缩的第一个字符为M,并且区间内只有这一个M,f[l][r][0]为在l到r中压缩的第一个字符为M,并且区间内有两个及以上的M

然后显然的转移是f[i][j][1]=min(f[i][k][0],f[i][k][1])+min(f[k+1][j][0],f[k+1][j][1])+1,f[i][j][0]=f[i][j][0],f[i][k][0]+j-k

然后考虑合并串,也就是当(l,mid),(mid+1,r)的串相等的时候,转移f[i][j][0]=f[i][(i+j)>>1][0]+1

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,f[60][60][2];
char s[60];
bool ok(int l,int r)
{
    int mid=(l+r)>>1;
    for(int i=1;i<=mid-l+1;i++)
        if(s[l+i-1]!=s[mid+i])
            return 0;
    return 1;
}
int main()
{
    scanf("%s",s+1);
    n=strlen(s+1);
    for(int i=n;i>=1;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][1]=min(f[i][j][1],min(f[i][k][0],f[i][k][1])+min(f[k+1][j][0],f[k+1][j][1])+1);
            for(int k=i;k<j;k++)
                f[i][j][0]=min(f[i][j][0],f[i][k][0]+j-k);
            if((j-i+1)%2==0&&ok(i,j))
                f[i][j][0]=min(f[i][j][0],f[i][(i+j)>>1][0]+1);
        }
    printf("%d",min(f[1][n][0],f[1][n][1]));
    return 0;
}

原文地址:https://www.cnblogs.com/lokiii/p/9650289.html

时间: 2024-08-11 09:52:38

bzoj 1068: [SCOI2007]压缩【区间dp】的相关文章

BZOJ 1068 [SCOI2007]压缩 区间DP

题意:链接 方法:区间DP 解析: MD写题解(吐槽)写到一半markdown挂了什么鬼! 要不要这样!你知道我的内心是什么样的吗! 吐槽,啊呸,写题解写到一半突然丢失了我的内心是崩溃的好吗! 来我们重新写题解(吐槽) 这道题我刚开始列了个瞎(和谐)动规(二维的裸区间) 加上乱七八糟的判断是否有M后,居然有交叉! 一定是我逻辑错误,对就是这样! 后来又是一顿瞎(和谐)搞之后,代码抽的爆炸,然后我一测,c-free挂掉- - 过了一个小时后,我选择死亡. 然后看了一眼hzw的题解. 看到那个三维之

bzoj 1068: [SCOI2007]压缩 DP

1068: [SCOI2007]压缩 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 496  Solved: 315[Submit][Status] Description 给一个由小写字母组成的字符串,我们可以用一种简单的方法来压缩其中的重复信息.压缩后的字符串除了小写字母外还可以(但不必)包含大写字母R与M,其中M标记重复串的开始,R重复从上一个M(如果当前位置左边没有M,则从串的开始算起)开始的解压结果(称为缓冲串). bcdcdcdcd可以

[BZOJ 1068] [SCOI2007] 压缩 【区间 DP 】

题目链接:BZOJ - 1068 题目分析 这种区间 DP 之前就做过类似的,也是字符串压缩问题,不过这道题稍微复杂一些. 需要注意如果某一段是 S1S1 重复,那么可以变成 M + Solve(S1) + R ,不过这个 Solve(S1) 中不能在中间有 M ,否则后面的 R 向前找到的 M 就不再是开头的 M 了. 代码 #include <iostream> #include <cstdio> #include <cstring> #include <al

B1068 [SCOI2007]压缩 区间dp

这个题我状态想对了,但是转移错了...dp的代码难度都不大,但是思考含量太高了..不会啊,我太菜了. 其实这个题就是一个正常的区间dp,中间多了一个特判的转移就行了. 题干: Description 给一个由小写字母组成的字符串,我们可以用一种简单的方法来压缩其中的重复信息.压缩后的字符串除了小 写字母外还可以(但不必)包含大写字母R与M,其中M标记重复串的开始,R重复从上一个M(如果当前位置左边没 有M,则从串的开始算起)开始的解压结果(称为缓冲串). bcdcdcdcd可以压缩为bMcdRR

bzoj 1068: [SCOI2007]压缩

做之前可以先做一下这题 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为

【BZOJ】1068: [SCOI2007]压缩(dp)

http://www.lydsy.com/JudgeOnline/problem.php?id=1068 发现如果只设一维的话无法转移 那么我们开第二维,发现对于前i个来说,如果确定了M在哪里,第i个是用R还是不用就能确定了(如果用R那么在中间一定变成了缓冲串) 那么可以转移了 设d[i,j]表示前i个串,最近的一个M在i的前边一个格子,的最短长度,有 d[1,1]=1 d[i,i]=min{d[i-1,j]}+2 //即用一次M又补上i,所以+2 d[i,j]=d[pos,j]+1,其中pos

【BZOJ-1068】压缩 区间DP

1068: [SCOI2007]压缩 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 1001  Solved: 615[Submit][Status][Discuss] Description 给一个由小写字母组成的字符串,我们可以用一种简单的方法来压缩其中的重复信息.压缩后的字符串除了小写字母外还可以(但不必)包含大写字母R与M,其中M标记重复串的开始,R重复从上一个M(如果当前位置左边没有M,则从串的开始算起)开始的解压结果(称为缓冲串). b

BZOJ 1055 玩具取名(区间DP)

很显然的区间DP,定义dp[i][j][k], 如果dp[i][j][k]=1表示字符串[i,j]可以组成k字符. # include <cstdio> # include <cstring> # include <cstdlib> # include <iostream> # include <vector> # include <queue> # include <stack> # include <map>

BZOJ 1090 字符串折叠(区间DP)

很明显的区间DP,设dp[l][r]表示[l,r]区间的字符串折叠后的最小长度. 可以通过两种方向转移,dp[l][r]=min(dp[l][i]+dp[i+1][r]). 另一种是折叠,dp[l][r]=min(dp[l][l+k-1]+cal((r-l+1)/k)+2).其中k是能整除(r-l+1)的数且区间能够折叠成k份,cal()函数计算数字的位数. 另外用了线段树维护hash值,可以每次验证logn. # include <cstdio> # include <cstring&