题意:
给三个整数n,l,r,和一个字符串s,满足l<=|c0-c1|<=r就可以切成字符串a和字符串b,c0为字符串a左侧出现0的次数,c1为字符串b右侧出现1的次数,求最多切割次数
知识点:区间dp
分析:先用前缀和求出数组c1和c0,假设我们在k点进行切割,就可以每次更新dp[l][r],先算出左区间[l,k]的0的个数为c00=c0[k]-c0[l-1],算出右区间[k+1,r]的1的个数为c11=c1[r]-c1[k],符合条件的每次更新区间dp,核心代码dp[l][r]=max(dp[l][r],1+dp[l][k]+dp[k+1][r])。
#include<bits/stdc++.h>
using namespace std;
int dp[510][510],c0[510],c1[510];
int main(){
int n,L,R;cin>>n>>L>>R;string s;cin>>s;
for(int i=1;i<=n;i++){
c1[i]=c1[i-1];
c0[i]=c0[i-1];
if(s[i-1]=='1')c1[i]++;
else c0[i]++;
}
for(int len=1;len<=n;len++){
for(int l=1;l<=n;l++){
int r=l+len-1;
if(r>n)break;
for(int k=l;k<r;k++){
int c00=c0[k]-c0[l-1];
int c11=c1[r]-c1[k];
if(abs(c00-c11)>=L&&abs(c00-c11)<=R){
dp[l][r]=max(dp[l][r],dp[l][k]+dp[k+1][r]+1);
}
}
}
}
cout<<dp[1][n];
}