B1068 [SCOI2007]压缩 区间dp

这个题我状态想对了,但是转移错了。。。dp的代码难度都不大,但是思考含量太高了。。不会啊,我太菜了。

其实这个题就是一个正常的区间dp,中间多了一个特判的转移就行了。

题干:

Description

  给一个由小写字母组成的字符串,我们可以用一种简单的方法来压缩其中的重复信息。压缩后的字符串除了小
写字母外还可以(但不必)包含大写字母R与M,其中M标记重复串的开始,R重复从上一个M(如果当前位置左边没
有M,则从串的开始算起)开始的解压结果(称为缓冲串)。 bcdcdcdcd可以压缩为bMcdRR,下面是解压缩的过程

  另一个例子是abcabcdabcabcdxyxyz可以被压缩为abcRdRMxyRz。

Input

  输入仅一行,包含待压缩字符串,仅包含小写字母,长度为n。

Output

  输出仅一行,即压缩后字符串的最短长度。

Sample Input

bcdcdcdcdxcdcdcdcd

Sample Output

12

HINT

在第一个例子中,解为aaaRa,在第二个例子中,解为bMcdRRxMcdRR。

【限制】

100%的数据满足:1<=n<=50 100%的数据满足:1<=n<=50

代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
#define duke(i,a,n) for(int i = a;i <= n;i++)
#define lv(i,a,n) for(int i = a;i >= n;i--)
#define clean(a) memset(a,0,sizeof(a))
const int INF = 1 << 30;
typedef long long ll;
typedef double db;
template <class T>
void read(T &x)
{
    char c;
    bool op = 0;
    while(c = getchar(), c < ‘0‘ || c > ‘9‘)
        if(c == ‘-‘) op = 1;
    x = c - ‘0‘;
    while(c = getchar(), c >= ‘0‘ && c <= ‘9‘)
        x = x * 10 + c - ‘0‘;
    if(op) x = -x;
}
template <class T>
void write(T x)
{
    if(x < 0) putchar(‘-‘), x = -x;
    if(x >= 10) write(x / 10);
    putchar(‘0‘ + x % 10);
}
char s[100];
int n;
int f[100][100][3];
bool check(int l,int r)
{
    int mid = (l + r) >> 1;
    duke(i,1,mid - l + 1)
    {
        if(s[l + i - 1] != s[mid + i])
        return 0;
    }
    return 1;
}
int main()
{
    scanf("%s",s + 1);
    n = strlen(s + 1);
    lv(i,n,1)
    {
        duke(j,i,n)
        {
            f[i][j][0] = f[i][j][1] = j - i + 1;
            duke(k,i,j - 1)
                f[i][j][1] = min(f[i][j][1],min(f[i][k][0],f[i][k][1]) + 1 + min(f[k + 1][j][1],f[k + 1][j][0]));
            duke(k,i,j - 1)
                f[i][j][0] = min(f[i][j][0],f[i][k][0] + j - k);
            if((j - i + 1) % 2 == 0 && check(i,j))
                f[i][j][0] = f[i][(i + j) /    2][0] + 1;
        }
    }
    printf("%d\n",min(f[1][n][0],f[1][n][1]));
    return 0;
}

原文地址:https://www.cnblogs.com/DukeLv/p/9726779.html

时间: 2024-10-08 07:29:59

B1068 [SCOI2007]压缩 区间dp的相关文章

BZOJ 1068 [SCOI2007]压缩 区间DP

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

【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】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

【CCF】路径压缩 区间dp

[题意] 改编哈夫曼树,限制从左到右字母的编码按字典序递增 [思路] 因为是二进制编码,所以是二叉树: 因为是前缀码,所以每个字母都是叶子结点,不可能是内结点: 因为要按字典序递增,所以只能是相邻的结点结合,且排在前面的在左边,排在后面的在右边: 具有最优子结构性质:考虑f[i,j],可以由f[i,k]和f[k,j]转换而来,只要找一个根结点,然后左右孩子分别为f[i,k]和f[k,j]的根结点,即dp[i][j]=dp[i,k]+dp[k,j]+c [AC] 1 #include<iostre

[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

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][

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可以

hihoCoder #1320 : 压缩字符串 区间dp

/** 题目:hihoCoder #1320 : 压缩字符串 链接:https://hihocoder.com/problemset/problem/1320 描述 小Hi希望压缩一个只包含大写字母'A'-'Z'的字符串.他使用的方法是:如果某个子串 S 连续出现了 X 次,就用'X(S)'来表示. 例如AAAAAAAAAABABABCCD可以用10(A)2(BA)B2(C)D表示. 此外,这种压缩方法是可以嵌套的,例如HIHOHIHOCODERHIHOHIHOCODER可以表示成2(2(HIH

hdu 4570 Multi-bit Trie 区间DP入门

Multi-bit Trie 题意:将长度为n(n <= 64)的序列分成若干段,每段的数字个数不超过20,且每段的内存定义为段首的值乘以2^(段的长度):问这段序列总的内存最小为多少? 思路:区间的最值,区间DP; 枚举长度,在初始化时,将长度和20比较,小于20看成是一段,大于20时,因为不能压缩,直接全部分割就是了:之后枚举区间内部的所有值,这是并不需要考虑将这个区间一分为二后各自的长度是否大于20,因为在子结构中已经计算好了:直接去最优解即可: #include<iostream>