一道区间dp题
我们发现由于有了M的限制,所以合并区间的时候并不能直接合并,因为不是从区间左端点开始的
因此考虑三维状态设计
f[i][j][0/1]表示i-j中是否存在M
对于不存在的情况,他有两种更新方式,一种是直接合并,一种是当偶数时,可以折半合并
对于存在的情况,这个M相当于把一个大区间的合并变成了两个小区间,因为M之后的这一段的开头相当于M之后的第一个字母。因此我们枚举M的位置进行更新
#include<bits/stdc++.h> using namespace std; const int N=1e5+10; const int inf=0x3f3f3f3f; int f[110][100][2]; string s; bool check(int l,int r){ int mid=(l+r)>>1; for(int i=l;i<=mid;++i){ if(s[i]!=s[mid+i-l+1]) return false; } return true; } int main(){ ios::sync_with_stdio(false); int i,j,k; cin>>s; int n=s.size(); s=" "+s; for(int len=1;len<=n;len++){ for(i=1;i+len-1<=n;i++){ j=i+len-1; f[i][j][0]=len; f[i][j][1]=inf; for(k=i;k<=j;k++){ f[i][j][0]=min(f[i][j][0],f[i][k][0]+j-k); f[i][j][1]=min(f[i][j][1],min(f[i][k][1],f[i][k][0])+min(f[k+1][j][1],f[k+1][j][0])+1); } if(len%2==0&&check(i,j)){ f[i][j][0]=min(f[i][j][0],f[i][(i+j)/2][0]+1); } } } cout<<min(f[1][n][0],f[1][n][1])<<endl; return 0; }