zoukankan      html  css  js  c++  java
  • 洛谷 P4302 [SCOI2003]字符串折叠 题解

    每日一题 day68 打卡

    Analysis

    这道题很容易想到区间DP,但是在DP中还需要判断循环节的压缩这种情况。

    另外还有一点,缩写并不一定比之前的字符串优。

    eg. aaa -> 3(a)

    于是我们开始考虑如何处理压缩的情况。

    因为我们转移时是将两个子区间的答案合成到一个大区间内,即 dp[i][k] 和 dp[k+1][j] 推出 dp[i][j]

    所以我们不妨设 dp[i][k] 所表示的区间为循环节,如果判断该循环节合法,那么压缩后的答案即为循环节的答案 + 2 + 数字位数。

    于是我们得出 dp 方程:

    dp[ i ][ j ] = min( dp[ i ][ j ] , dp[ i ][ k ] + dp[ k + 1 ][ j ] ); //正常更新答案

    if (循环节合法) dp[ i ][ j ] = min( dp[ i ][ j ] , dp[ i ][ k ] + 2 + digit[ len / cyc ] ); //len为枚举的总区间长度,cyc为循环节长度

    那么现在唯一的问题就是如何判断循环节合法

    以下为限制条件:

    1.如果枚举的总区间长度可以整除循环节的长度

    2.判断 dp[ k + 1 ][ j ] 是否满足循环节 (这里的实现基本是暴力,看代码,很好懂)

    这样这道题就完成了

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define int long long
     6 #define maxn 100+10
     7 #define rep(i,s,e) for(register int i=s;i<=e;++i)
     8 #define dwn(i,s,e) for(register int i=s;i>=e;--i)
     9 using namespace std;
    10 inline int read()
    11 {
    12     int x=0,f=1;
    13     char c=getchar();
    14     while(c<'0'||c>'9') {if(c=='-') x=-x; c=getchar();}
    15     while(c>='0'&&c<='9') {x=x*10+c-'0'; c=getchar();}
    16     return f*x;
    17 }
    18 inline void write(int x)
    19 {
    20     if(x<0){putchar('-');x=-x;}
    21     if(x>9)write(x/10);
    22     putchar(x%10+'0');
    23 }
    24 int n;
    25 int digit[maxn];
    26 int dp[maxn][maxn];
    27 char a[maxn];
    28 inline bool check(int l,int r,int len)
    29 {
    30     for(register int i=l;i<=l+len-1;++i)
    31     {
    32         char ch=a[i];
    33         for(register int j=i;j<=r;j+=len)
    34         {
    35             if(a[j]!=ch) return false;
    36         }
    37     }
    38     return true;
    39 }
    40 signed main()
    41 {
    42     cin>>a+1;
    43     n=strlen(a+1);
    44     rep(i,1,9) digit[i]=1;
    45     rep(i,10,99) digit[i]=2;
    46     digit[100]=3;
    47     memset(dp,63,sizeof(dp));
    48     rep(i,1,100) dp[i][i]=1;
    49     rep(len,1,n)
    50     {
    51         for(register int i=1;i+len-1<=n;++i)
    52         {
    53             int j=i+len-1;
    54             rep(k,i,j-1)
    55             {
    56                 dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]);
    57                 int cyc=k-i+1;
    58                 if(len%cyc!=0) continue;
    59                 if(check(i,j,cyc)==true)
    60                 {
    61                     dp[i][j]=min(dp[i][j],dp[i][k]+2+digit[len/cyc]);
    62                 }
    63             }
    64         }
    65     }
    66     write(dp[1][n]);
    67     return 0;
    68 }

    如有失误请各位大佬斧正(反正我不认识斧正是什么意思)

  • 相关阅读:
    Div+CSS 布局
    Windows Mobile 参考:
    Linux export的作用
    CSS(2)基本语法
    HTML(6)超链接
    HTML(5)常用的格式标签
    HTML(8)表格
    CSS(1) CSS简介
    HTML(7)图像、背景和颜色
    HTML(10)框架
  • 原文地址:https://www.cnblogs.com/handsome-zyc/p/12372083.html
Copyright © 2011-2022 走看看