题目链接:https://www.luogu.com.cn/problem/P2470
分析:
这道题我是看题解2过的,但是对代码的理解存在问题,所以自个口胡一下。
对于0与1两种状态,我们先考虑1:很明显1要在0的基础上进行,f[l][r][1]=min(f[l][r][1],min(f[l][k][0],f[l][k][1])+min(f[k+1][r][0],f[k+1][r][1])+1),这里面的+1就是补M的操作,假如在l到r没有对称的话,这里+1明显不会作为答案,当+1作为答案时,前面两个min一定是取了有R的情况,也就是说,我们把M和R的放入操作分开,M是因为R才放入的。这么理解起来的话,前面0操作对M置之不理也就变得合理起来。
代码:
#include<iostream> #include<cstdio> #include<vector> #include<cstring> #include<algorithm> using namespace std; #define int long long #define R register #define debug printf("zjy ") inline int read(){ int a=0,b=1;char c=getchar(); while(!isdigit(c)){if(c=='-')b=-1;c=getchar();} while(isdigit(c)){a=a*10+c-'0';c=getchar();} return a*b; } int n,f[100][100][2]; char s[100]; bool check(int l,int r){ if((r-l+1)&1)return false; int mid=(l+r)>>1; for(R int i=0;i<((r-l+1)>>1);i++){ if(s[l+i]!=s[mid+1+i])return false; } return true; } signed main(){ scanf("%s",s+1); n=strlen(s+1); memset(f,0x3f,sizeof(f)); for(R int i=1;i<=n;i++){ for(R int j=i;j<=n;j++){ f[i][j][0]=f[i][j][1]=j-i+1; } } for(R int len=2;len<=n;len++){ for(R int l=1,r,mid;l+len-1<=n;l++){ r=l+len-1;mid=(l+r)>>1; if(check(l,r))f[l][r][0]=min(f[l][r][0],f[l][mid][0]+1); for(R int k=l;k<r;k++)f[l][r][0]=min(f[l][r][0],f[l][k][0]+r-k); for(R int k=l;k<r;k++)f[l][r][1]=min(f[l][r][1],min(f[l][k][0],f[l][k][1])+min(f[k+1][r][0],f[k+1][r][1])+1); } } printf("%lld ",min(f[1][n][0],f[1][n][1])); return 0; }