\(DP\)的实现也要下一下功夫,比如这题,知道转移方程却不会实现
定义f[i][j]
为区间\([i,j]\)折叠的最短长度
然后就是区间\(DP\)的套路,枚举中间断点,然后转移
如何判断能否折叠,以及折叠后的处理没有想到
还要多加练习
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define LL long long
using namespace std;
LL read() {
LL k = 0, f = 1; char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9')
k = k * 10 + c - 48, c = getchar();
return k * f;
}
int f[110][110]; char s[110];
bool cmp(int x, int k, int y) { //判断能否折叠
if(((y-x+1) % (k-x+1))) return false;
int pos = x;
for(int i = x; i <= y; ++i) {
if(s[i] != s[pos++]) return false;
if(pos > k) pos = x;
}
return true;
}
int calc(int x) { //折叠后的数字不一定只为个位数,要计算它的位数
int num = 0;
while(x) ++num, x /= 10;
return num;
}
int main() {
scanf("%s", s+1); int len = strlen(s+1);
memset(f, 127/3, sizeof(f));
for(int l = 0; l <= len; ++l)
for(int i = 1; i <= len-l+1; ++i) {
int j = i + l - 1; f[i][j] = l;
for(int k = i; k < j; ++k) {
if(!cmp(i, k, j)) f[i][j] = min(f[i][j], f[i][k] + f[k+1][j]);
else f[i][j] = min(f[i][j], f[i][k] + 2 + calc(l/(k-i+1)));
}
}
cout << f[1][len];
return 0;
}