bzoj1090:[SCOI2003]字符串折叠

区间DP算法详解

思路:区间dp,令f[l][r]表示l到r的答案,于是f[l][r]=min(f[l][mid],f[mid+1][r]),如果能折叠f[l][r]=min(f[l][r],f[l][l+len-1]+calc(r-l+1,len),calc是计算数字的长度。记忆化搜索即可。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 using namespace std;
 7  
 8 char s[105];
 9 int f[105][105];
10  
11 bool check(int l,int r,int len){
12     for (int i=l;;i+=len){
13         if (i+len>r) break;
14         for (int j=i;j<=i+len-1;j++)
15             if (s[j]!=s[j+len] && j+len<=r) return 0;
16     }
17     return 1;
18 }
19  
20 int calc(int n,int len){
21     int ans=0;n/=len;while (n) n/=10,ans++;return ans; 
22 }
23  
24 int dp(int l,int r){
25     if (l==r) return f[l][r]=1;
26     if (f[l][r]) return f[l][r];
27     int len=r-l+1;f[l][r]=r-l+1;
28     for (int mid=l;mid<r;mid++) f[l][r]=min(f[l][r],dp(l,mid)+dp(mid+1,r));
29     for (int L=1;L<len;L++) if (len%L==0 && check(l,r,L)) f[l][r]=min(f[l][r],dp(l,l+L-1)+2+calc(len,L));
30     return f[l][r];
31 }
32  
33 int main(){
34     scanf("%s",s+1);
35     printf("%d",dp(1,strlen(s+1)));
36     return 0;
37 }
View Code

转载于:https://www.cnblogs.com/DUXT/p/5944483.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值