字符串折叠
题解见luogu
dp问题要考虑所有完整的情况
1、将问题分治
2、分治后的合并处理(可能会与分无关,就是当做整体处理)
3、状态转换方程
想不通时,从最简单的样例出发
一定要想清楚,什么样的分治方法才是正确的(如何 合理的分解问题为子问题)
#include<cstdio>
#include<iostream>
#include<string>
#include<cmath>
#include<algorithm>
#include<map>
#include<set>
#include<vector>
using namespace std;
int dp[110][110];
int m[110];
string s;
bool check(int l,int r,int len){
for(int i=l;i<=r;i++){
if(s[i]!=s[(i-l)%len+l]) return false;
}
return true;
}
int main(){
cin >> s;
int L=s.size();
for(int i=0;i<=100;i++)
for(int j=0;j<=100;j++)
dp[i][j]=1<<20;
for(int i=0;i<=100;i++) dp[i][i]=1;
for(int i=0;i<=9;i++) m[i]=1;
for(int i=10;i<=99;i++) m[i]=2;
m[100]=3;
for(int l=2;l<=L;l++){
for(int i=0,j=i+l-1;j<L;i++,j++){
for(int k=i;k<j;k++){
dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]);
}
for(int k=i;k<j;k++){
int len=k-i+1;
if(l%len!=0) continue;
if(check(i,j,len))
dp[i][j]=min(dp[i][j],dp[i][k]+m[l/len]+2);
}
}
}
cout << dp[0][L-1];
return 0;
}