• [SCOI2007]压缩 题解


    题目描述

    给一个由小写字母组成的字符串,我们可以用一种简单的方法来压缩其中的重复信息。压缩后的字符串除了小写字母外还可以(但不必)包含大写字母R与M,其中M标记重复串的开始,R重复从上一个M

    (如果当前位置左边没有M,则从串的开始算起)开始的解压结果(称为缓冲串)。bcdcdcdcd可以压缩为bMcdRR,下面是解压缩的过程:

    已经解压的部分解压结果缓冲串
    b b b
    bM b .
    bMc bc c
    bMcd bcd cd
    bMcdR bcdcd cdcd
    bMcdRR bcdcdcdcd cdcdcdcd

     

    输入格式

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

    输出格式

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

    输入输出样例

    输入 #1
    aaaaaaa
    输出 #1
    5
    输入 #2
    bcdcdcdcdxcdcdcdcd
    输出 #2
    12
    分析:
    • 本题显然跟字符串有很大关系,显然看一下题意为区间DP,区间DP好题。
    • 设dp[i][j][0]表示i到j的区间内没有M的情况,dp[i][j][1]则表示i到j的区间内有M的情况。
    • 先讨论i到j区间没有M的情况,若前半段和后半段相等 dp[i][j][0]=min(dp[i][j][0],dp[i][mid][0]+1)mid为区间中点;若跟平常的dp一样的话,枚举中间点k,dp[i][j][0]=min(dp[i][j][0],dp[i][k][0]+j-k)
    • 再讨论i到j区间内有M的情况,此时k枚举的是M的位置。dp[i][j][1]=min(dp[i][j][1],min(dp[i][k][0],dp[i][k][1])+min(dp[k+1][j][0],dp[k+1][j][1])+1).
    • 最后输出min(dp[i][j][0],dp[i][j][1])

    代码

     1 #include<bits/stdc++.h>
     2 #define re register int
     3 #define ll long long
     4 #define maxn 55
     5 using namespace std;
     6 char as[maxn];
     7 int dp[maxn][maxn][3];
     8 int n;
     9 int check(int l,int r){
    10     if((r-l+1)&1)return 0;
    11     int mid=(l+r)>>1;
    12     for(re i=l;i<=mid;i++)
    13         if(as[i]!=as[i+mid-l+1])return 0;
    14     return 1;
    15 }//判断前一段和后一段是否相等 
    16 int main(){
    17     scanf("%s",as+1);
    18     n=strlen(as+1);//长度 
    19     memset(dp,0x3f,sizeof(dp));
    20     for(re i=1;i<=n;i++)
    21         for(re j=i;j<=n;j++)
    22             dp[i][j][0]=dp[i][j][1]=(j-i+1);//初始为区间长度 
    23     for(re len=2;len<=n;len++)
    24         for(re l=1;l+len-1<=n;l++){
    25             int r=l+len-1;
    26             if(check(l,r))dp[l][r][0]=min(dp[l][(l+r)/2][0]+1,dp[l][r][0]);//相等的话 
    27         for(re k=l;k<r;k++){
    28             dp[l][r][0]=min(dp[l][r][0],dp[l][k][0]+r-k);//普通区间dp 
    29         }
    30         for(re k=l;k<r;k++)
    31             dp[l][r][1]=min(dp[l][r][1],min(dp[l][k][0],dp[l][k][1])+min(dp[k+1][r][0],dp[k+1][r][1])+1);//后面有M的时候 
    32         }
    33         printf("%d
    ",min(dp[1][n][1],dp[1][n][0]));//输出最后的结果 
    34     return 0;
    35 }

    虽然渺小,但不放弃。

     
  • 相关阅读:
    storm从入门到放弃(三),放弃使用 StreamId 特性
    10、图像的几何变换——平移、镜像、缩放、旋转、仿射变换
    滚动条控件
    控件添加——静态控件、编辑框控件、命令按钮、复选框和单选按钮控件
    9、图像处理基础运算
    控件——静态空间、编辑框控件、命令按钮、复选框和单选控件
    Visual C++.NET设计
    CMD指令及其意义
    OpenCV与QT联合开发示例
    OpenCV基础知识介绍
  • 原文地址:https://www.cnblogs.com/yzzy/p/13292234.html
Copyright © 2020-2023  润新知