B1068 [SCOI2007]压缩 区间dp

Posted dukelv

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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
",min(f[1][n][0],f[1][n][1]));
    return 0;
}

 

以上是关于B1068 [SCOI2007]压缩 区间dp的主要内容,如果未能解决你的问题,请参考以下文章

Luogu 2470 [SCOI2007]压缩

[SCOI2007]压缩

BZOJ-1068压缩 区间DP

BZOJ 1068 SCOI2007 压缩

luogu P2470 [SCOI2007]压缩

[bzoj1072][SCOI2007][排列perm] (状态压缩+数位dp+排列去重)