[luoguP4302] [SCOI2003] 字符串折叠 解题报告(区间DP)
题目链接:https://www.luogu.org/problemnew/show/P4302
题解:
我们考虑折叠一个区间里的字符串,怎么样才是最优的
1.把这个区间分成几部分分别折叠
2.把这个区间直接折叠
注意到后者我们还需要考虑括号和数字的长度
#include<algorithm> #include<cstring> #include<cstdio> #include<iostream> using namespace std; const int N=100+15; string s; int n; int f[N][N]; int check(int l,int m,int r) { int len2=r-l+1,len1=m-l+1; if (len2%len1) return -1; int x=len2/len1; for (int i=1;i<=x;i++) { int tt=l+(i-1)*len1; for (int j=0;j<len1;j++) { if (s[l+j-1]!=s[tt+j-1]) return -1; } } int cnt=0; while (x) x/=10,cnt++; return cnt; } int main() { memset(f,0x3f3f,sizeof(f)); cin>>s; n=s.size(); for (int i=1;i<=n;i++) f[i][i]=1; for (int len=2;len<=n;len++) for (int l=1;l<=n-len+1;l++) { int r=l+len-1; f[l][r]=len; for (int k=l;k<r;k++) { f[l][r]=min(f[l][r],f[l][k]+f[k+1][r]); int x=check(l,k,r); if (x!=-1) { f[l][r]=min(f[l][r],x+2+f[l][k]); } } } printf("%d\n",f[1][n]); return 0; }
星星之火,终将成燎原之势