【洛谷 P4302】 [SCOI2003]字符串折叠(DP)

题目链接
简单区间dp
\(f[i][j]\)表示\([i,j]\)的最短长度
先枚举区间,然后在区间中枚举长度\(k\),看这个区间能不能折叠成几个长度为\(k\)的,如果能就更新答案。

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
char s[110];
int f[110][110], n, num[110];
string p[110][110];
inline int check(int a, int b, int c){
	int d = b - a + 1;
	for(int i = c; i < d; ++i)
		if(s[a + i] != s[a + (i % c)])
			return 0;
	return 1;
}
int main(){
	while(scanf("%s", s + 1) != EOF){
		n = strlen(s + 1);
		for(int i = 1; i <= 9; ++i) num[i] = 1;
		for(int i = 10; i <= 99; ++i) num[i] = 2;
		num[100] = 3;
		for(int i = 1; i <= n; ++i)
			f[i][i] = 1;
		for(int l = 2; l <= n; ++l)
			for(int i = 1; i + l - 1 <= n; ++i){
				int j = i + l - 1;
				f[i][j] = l;
				for(int k = 1; k < l; ++k){
					f[i][j] = min(f[i][j], f[i][i + k - 1] + f[i + k][j]);
					if(l % k == 0)
						if(check(i, j, k))
							f[i][j] = min(f[i][j], 2 + num[l / k] + f[i][i + k - 1]);
				}
			}
		printf("%d\n", f[1][n]);
	}
	return 0;
}
posted @ 2019-10-05 09:15  Qihoo360  阅读(133)  评论(0编辑  收藏  举报
You're powerful!