字符串折叠 bzoj-1090 SCOI-2003
题目大意:我说不明白...链接
注释:自己看
想法:动态规划
状态:dp[i][j]表示从第i个字符到第j个字符折叠后的最短长度。
转移:dp[l][r]=min(r-l+1,dp[l][k]+dp[k+1][r])
当k+1~r可以有l~k得到时还要
dp[l][r]=min(dp[l][r],dp[l][k]+2+calc((r-l+1)/(k-l+1)));//calc用来计算一个十进制数所占位数
最后,附上丑陋的代码... ...
#include <iostream> #include <cstdio> #include <cstring> using namespace std; char s[101]; int f[101][101]; bool mark[101][101]; bool jud(int l,int r,int cl,int cr) { if((r-l+1)%(cr-cl+1)!=0)return false; for(int i=l;i<=r;i++) if(s[i]!=s[(i-l)%(cr-cl+1)+cl])return false; return true; } int get(int x) { int t=0; while(x) { x/=10;t++; } return t; } int dp(int l,int r) { if(l==r)return 1; if(mark[l][r])return f[l][r]; mark[l][r]=1; int t=r-l+1; for(int i=l;i<r;i++) { t=min(t,dp(l,i)+dp(i+1,r)); if(jud(i+1,r,l,i)) t=min(t,dp(l,i)+2+get((r-i)/(i-l+1)+1)); } return f[l][r]=t; } int main() { scanf("%s",s); printf("%d",dp(0,strlen(s)-1)); return 0; }
小结:好题,就是那个十进制的太不要脸了.......