啊没错又是dp
啊没错又是区间dp
设 dp[i][j] 为区间 i~j 的最短折叠长度
转移 , 情况有两种
第一种是把两个已经折叠好的区间合并
另一种是把这个区间折叠掉
对于第一种 , 很一般的枚举断点然后合并
对于后一种呐?
枚举折叠后的长度(不算括号和系数的长度)
因为是要折掉整个区间 , 所以要枚举的长度是总长度的因数 , 很显然只需要枚举总长度的一半
然后呐 , 怎么检测能否折叠?
写一个函数 , 叫他 check() 吧
就来比较暴力的判断能否折来
对于系数的长度
我写了一个divide() 函数 , 不过因为数据范围只有100 , 所以最多只有三种情况 , 分别判断一下就好了
代码 :
1 #include<cmath> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<iostream> 6 #include<algorithm> 7 #define APART puts("----------------------") 8 #define debug 1 9 #define FILETEST 1 10 #define inf 1010 11 #define ll long long 12 #define ha 998244353 13 #define INF 0x7fffffff 14 #define INF_T 9223372036854775807 15 #define DEBUG printf("%s %d\n",__FUNCTION__,__LINE__) 16 17 namespace chino{ 18 19 inline void setting(){ 20 #if FILETEST 21 freopen("_test.in", "r", stdin); 22 freopen("_test.me.out", "w", stdout); 23 #endif 24 return; 25 } 26 27 inline int read(){ 28 char c = getchar(), up = c; int num = 0; 29 for(; c < '0' || c > '9'; up = c, c = getchar()); 30 for(; c >= '0' && c <= '9'; num = (num << 3) + (num << 1) + (c ^ '0'), c = getchar()); 31 return up == '-' ? -num : num; 32 } 33 34 int n; 35 char s[inf]; 36 int dp[inf][inf]; 37 38 using std::min; 39 40 inline bool check(int l, int r, int k){ 41 for(int i = 0; i < k; i++){ 42 for(int j = i; j + k + l <= r; j += k){ 43 if(s[j + l] != s[j + l + k]) 44 goto A; 45 } 46 } 47 return 1; 48 A: return 0; 49 } 50 51 inline int divide(int num){ 52 char s[5] = ""; 53 sprintf(s, "%d", num); 54 return strlen(s); 55 } 56 57 inline int main(){ 58 memset(dp, 10, sizeof dp); 59 scanf("%s", s + 1); 60 n = strlen(s + 1); 61 for(int l = n; l; l--){ 62 dp[l][l] = 1; 63 for(int r = l + 1; r <= n; r++){ 64 int len = r - l + 1; 65 dp[l][r] = len; 66 for(int k = l; k < r; k++) 67 dp[l][r] = min (dp[l][r], dp[l][k] + dp[k + 1][r]); 68 for(int k = 1; k <= (len >> 1); k++){ 69 if(len % k == 0 && check(l, r, k)) 70 dp[l][r] = min (dp[l][r], dp[l][k + l - 1] + 2 + divide(len / k)); 71 } 72 } 73 } 74 printf("%d\n", dp[1][n]); 75 return 0; 76 } 77 78 }//namespace chino 79 80 int main(){return chino::main();}