zoukankan      html  css  js  c++  java
  • Evanyou Blog 彩带

      题目传送门

    字符串折叠

    题目描述

    折叠的定义如下:

    1. 一个字符串可以看成它自身的折叠。记作S = S
    2. X(S)是X(X>1)个S连接在一起的串的折叠。记作X(S) = SSSS…S(X个S)。
    3. 如果A = A’, B = B’,则AB = A’B’ 例如,因为3(A) = AAA, 2(B) = BB,所以3(A)C2(B) = AAACBB,而2(3(A)C)2(B) = AAACAAACBB

      给一个字符串,求它的最短折叠。例如AAAAAAAAAABABABCCD的最短折叠为:9(A)3(AB)CCD。

    输入输出格式

    输入格式:

     

    仅一行,即字符串S,长度保证不超过100。

     

    输出格式:

     

    仅一行,即最短的折叠长度。

     

    输入输出样例

    输入样例#1: 复制
    NEERCYESYESYESNEERCYESYESYES
    输出样例#1: 复制
    14

    说明

    一个最短的折叠为:2(NEERC3(YES))


      分析:

      K_lord的考试里面出的题目。考的时候直接弃疗。。。(先膜一波老余AK%%%)

      需要用区间DP来做,首先定义动规数组f[l][r],表示从l到r这一段区间内的字符串折叠后能得到的最短结果。那么枚举折叠的区间,然后枚举左右区间,再枚举可折叠的长度,也就是枚举区间长度的所有因数,然后进行判断该区间是否可以折叠,如果可以则进行状态转移。值得注意的是,转移完以后还需要在进行依次断点枚举,表示将该区间分成两次折叠,看能否得到最短折叠。当然,蒟蒻不擅长动规,还是听了老余讲课,又参考了大佬的博客才弄懂的。如果上面的思路不太懂,就直接看代码吧,代码好懂多了。

      Code:

    #include<bits/stdc++.h>
    using namespace std;
    char s[107];int f[107][107];
    inline bool check(int l,int r,int k)
    {
      for(int i=l+k,p=0;i<=r;i++,p=(p+1)%k)
        if(s[i]!=s[l+p])return false;
      return true;
    }
    inline int get(int x)
    {int ret=2;while(x)x/=10,ret++;return ret;}
    int main()
    {
      memset(f,0x7f,sizeof(f));
      scanf("%s",s+1);int n=strlen(s+1);
      for(int i=1;i<=n;i++)f[i][i]=1;
      for(int i=2;i<=n;i++)
        for(int l=1;l+i-1<=n;l++){
          int r=l+i-1;
          for(int k=1;k*k<=i;k++){
        if(i%k==0){
          if(check(l,r,i/k))f[l][r]=min(f[l][r],f[l][l+i/k-1]+get(k));
          if(check(l,r,k))f[l][r]=min(f[l][r],f[l][l+k-1]+get(i/k));}}
          for(int k=l;k<=r;k++)
        f[l][r]=min(f[l][r],f[l][k]+f[k+1][r]);}
      printf("%d",f[1][n]);return 0;
    }
  • 相关阅读:
    蓝桥杯---打印回型嵌套(简单递归)
    蓝桥杯---分酒
    蓝桥杯---简单试题集锦
    蓝桥杯---黑洞数
    2013蓝桥杯B组 预赛试题
    2012蓝桥杯预赛--取球博弈
    2012第三届蓝桥杯预赛题
    C中的动态开辟(malloc)
    文件的输入输出
    hdoj 1233 还是畅通工程
  • 原文地址:https://www.cnblogs.com/cytus/p/9099792.html
Copyright © 2011-2022 走看看