BZOJ 1090 [SCOI 2003] 字符串折叠 (区间DP)

来源:互联网 发布:数据库更新语句 编辑:程序博客网 时间:2024/06/01 10:06

题目链接:BZOJ 1090

dp[i][j]表示区间[i,j]的最短折叠长度
转移方程为:dp[i][j]=min(j-i+1,dp[i][k]+dp[k+1][j])
特别地若满足区间[k+1,j]可以由区间[i,k]多次折叠得到,那么
dp[i][j]=min(dp[i][j],dp[i][k]+2+get((j-k)/(k-i+1)+1))//get函数是求一个数的位数

#include<cstdio>#include<cstring>#include<iostream>using namespace std;char s[110];int dp[110][110];int wei(int x){int tot=0;while(x){tot++; x/=10;}return tot;}bool jud(int a,int b,int c,int d){int t=0;for(int i=c;i<=d;i++){if(s[i]!=s[a+t])return false;t++;if(t==b-a+1)t=0;}if(t!=0)return false;else return true;}int get(int l,int r){if(l==r)return 1;if(dp[l][r])return dp[l][r];int t=r-l+1;for(int i=l;i<r;i++){t=min(t,get(l,i)+get(i+1,r));if(jud(l,i,i+1,r)){t=min(t,get(l,i)+2+wei((r-i)/(i-l+1)+1));}}return dp[l][r]=t;}int main(){scanf("%s",s);int l=strlen(s);for(int i=l;i>=1;i--)s[i]=s[i-1];printf("%d\n",get(1,l));return 0;}


0 0