8
28
2015
0

1090: [SCOI2003]字符串折叠

1090: [SCOI2003]字符串折叠

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))

 

 

 

区间DP

题解详见 Hzwer学长博客

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#define MaxN 101
char s[MaxN];
int len,f[MaxN][MaxN];
bool check(int l,int r,int x,int y){
	int s1=(r-l+1);
	int s2=(y-x+1);
	if (s1%s2) return false;
	int j=x;
	for (int i=l;i<=r;++i){
	    if (s[i]!=s[j]) return false;
		++j;
		if (j>y) j=x;
	}
    return true;
}
int get(int x){
	int s=0;
	for (;x;x/=10,++s);
	return s;
}
int calc(int l,int r){
	if (l==r) return 1;
	if (f[l][r]) return f[l][r];
	int ans=r-l+1;
	for (int i=l;i<r;++i){
		ans=min(ans,calc(l,i)+calc(i+1,r));
		if (check(l,i,i+1,r))
		    ans=min(ans,calc(i+1,r)+2+get((i-l+1)/(r-i)+1));
	}
	f[l][r]=ans;
	return f[l][r];
}
int main(){
	scanf("%s",s+1);
	len=strlen(s+1);
	printf("%d\n",calc(1,len));
}
Category: BZOJ | Tags: bzoj DP | Read Count: 415

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com