bzoj1068: [SCOI2007]压缩
题目链接
题解
这道题对于语文不好的我很不友好啊
啥东西啊这是QAQ,题意理解了半天,还是错的QAQQQQ
f[i][j][0] -> i到j中间没有M,f[i][j][1] -> i到j中有M
f[i][j][0] = min(f[i][k][0] + f[k + 1][j][0] + 1) i到j这一段可以拆成i到k和k+1到j,中间加一个M
f[i][j][t] = min(f[i][k][t] + j - k) 压缩i到k段,后一段不管
f[i][j][t]=min(f[i][(i+j)>>1][t]+1),如果可以分为两串相同的话,从中间劈开压缩加一个R
#include<cstdio>
#include<cstring>
#include<algorithm>
const int maxn = 57;
char s[maxn];
int ans = 0,dp[maxn][maxn][2] ;
bool judge(int l,int r) {
int len = r - l + 1;
if(len & 1) return false;
for(int i = l;i <= l + r >> 1;++ i)
if(s[i] != s[i + len / 2]) return false;
return true;
}
int dfs(int l,int r,int t) {
if(dp[l][r][t] != -1) return dp[l][r][t];
int ret = r - l + 1;
if(ret == 1) return ret;
if(t) for(int i = l;i < r;++ i)
ret = std::min(ret,dfs(l,i,t) + dfs(i + 1,r,t) + 1);
for(int i = l;i < r;++ i) ret = std::min(ret,dfs(l,i,t) + r - i);
if(judge(l,r)) ret = std::min(ret,dfs(l,(l + r) >> 1,0) + 1);
return dp[l][r][t] = ret;
}
int main() {
scanf("%s",s + 1);
int len = strlen(s + 1);
memset(dp,-1,sizeof dp);
printf("%d\n",dfs(1,len,1));
return 0;
}