1. 程式人生 > >bzoj 1090

bzoj 1090

name 之間 scoi2003 false mit clas 判斷 online geo

1090: [SCOI2003]字符串折疊

Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 1413 Solved: 936
[Submit][Status][Discuss]

Description

折疊的定義如下: 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。

Input

僅一行,即字符串S,長度保證不超過100。

Output

僅一行,即最短的折疊長度。

Sample Input

NEERCYESYESYESNEERCYESYESYES

Sample Output

14

HINT

一個最短的折疊為:2(NEERC3(YES))

思路:f[i][j]表示i到j折疊的最小長度,f[i][j]=min(f[i][j],f[i][k]+f[k+1][j],在i--j如果可折疊的話,那麽k+1--j為幾倍的i---k,判斷下

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3
4 char s[101]; 5 int f[101][101]; 6 bool mark[101][101]; 7 8 9 int get(int x){ 10 int sum=0; 11 while(x){ 12 x/=10;sum++; 13 } 14 return sum; 15 } 16 17 bool hh(int l,int r,int cl,int cr){//l-r之間可以由幾個cl-cr得到 18 if((r-l+1)%(cr-cl+1)) return false; 19 int x=cl; 20 for
(int i=l;i<=r;i++){ 21 if(s[i]!=s[x++])return false; 22 if(x==cr+1) x=cl; 23 } 24 return true; 25 } 26 27 int dp(int l,int r){ 28 if(l==1&&r==1) return 1; 29 if(mark[l][r]) return f[l][r]; 30 mark[l][r]=1; 31 int t=r-l+1; 32 for(int i=l;i<r;i++){ 33 t=min(t,dp(l,i)+dp(i+1,r)); 34 if(hh(i+1,r,l,i)){//可重復 35 t=min(t,dp(l,i)+2+get((r-i)/(i-l+1)+1)); 36 } 37 } 38 return f[l][r]=t; 39 } 40 int main(){ 41 scanf("%s",s); 42 printf("%d\n",dp(0,strlen(s)-1)); 43 }

bzoj 1090