zoukankan      html  css  js  c++  java
  • bzoj 1090 [SCOI2003]字符串折叠(区间DP)

    【题目链接】

        http://www.lydsy.com/JudgeOnline/problem.php?id=1090

    【题意】

        给定一个字符串,问将字符串折叠后的最小长度。

    【思路】

        设f[i][j]表示将区间ij折叠后的最小长度,则有转移式:

            f[i][j]=min{ j-i+1,f[i][k]+f[k+1][j],f[i][i+x-1]+2+digit((j-i+1)/x) }

        第一项代表不折叠,第二项代表当前不折叠,第三项代表以x长度折叠ij区间,条件是满足ij区间以x为循环节。

    【代码】

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 using namespace std;
     5 
     6 const int N = 5e2+10;
     7 
     8 int n;
     9 char s[N];
    10 int f[N][N];
    11 
    12 int digit(int x) 
    13 {
    14     return x<10? 1:(x<100?2:3);
    15 }
    16 int dp(int l,int r) 
    17 {
    18     int& ans=f[l][r];
    19     if(ans>=0) return ans;
    20     if(l==r) return ans=1;
    21     int len=r-l+1; ans=len;
    22     for(int k=l;k<r;k++)
    23         ans=min(ans,dp(l,k)+dp(k+1,r));
    24     for(int x=1;x<=len;x++) if(len%x==0) {
    25         int flag=0;
    26         for(int i=l;i<=l+x-1;i++) {
    27             int j=i+x;
    28             while(j<=r) {
    29                 if(s[i]!=s[j]) { flag=1; break; }
    30                 j+=x;
    31             }
    32             if(flag==1) break;
    33         }
    34         if(!flag) ans=min(ans,dp(l,l+x-1)+2+digit(len/x));
    35     }
    36     return ans;
    37 }
    38 
    39 int main()
    40 {
    41     scanf("%s",s);
    42     n=strlen(s);
    43     memset(f,-1,sizeof(f));
    44     printf("%d
    ",dp(0,n-1));
    45     return 0;
    46 }

        

  • 相关阅读:
    CSS:CSS 创建
    mfs-用户
    java实现扑克牌移动
    java实现扑克牌移动
    java实现扑克牌移动
    java实现纵横火柴棋
    java实现纵横火柴棋
    java实现纵横火柴棋
    java实现纵横火柴棋
    java实现纵横火柴棋
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5297179.html
Copyright © 2011-2022 走看看