#### 题目描述
jackle 在校赛的时候出过一道 "切割 01 串" 的题目,如今他又出了一道切割 01 串的题目:
给定一个长度为 n 的 01 串,定义如下操作为一次 "切割":
将长度大于 1 的字符串分割为两个非空的连续字串,记分割出来的左侧字串 a 中 0 的出现次数为 C0,右侧字串 b 中 1 出现的次数为 C1,需要满足L≤|C0−C1|≤R。
你每次切割完,都会得到两个新 01 串,你可以继续选择这些已经被你切出来的 01 串做切割,只要满足切割条件。
jackle 想问你最多可以切割多少次?
#### 输入描述:
第一行输入 3 个整数,n (1≤n≤500),L,R (0≤L≤R≤500),分别表示字符串长度,和题目中的两个参数。
第二行输入 1 个长度为 n 的 01 串。
#### 输出描述:
输出最多能切割多少次?
输入
6 2 3 011011
输出
3
说明
其中一种切割次数最多的切法如下: 第一次切割可以切:0 ∣ 11011,然后选择 11011 这个串继续做切割。 第二次切割可以切:1 ∣ 1011,然后选择 1011 这个串继续做切割。 第三次切割可以切:1 ∣ 011。
#include<bits/stdc++.h>
using namespace std;
int n, l, r;
string s;
int c0[550], c1[550],dp[550][550];
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin>>n>>l>>r;
cin>>s;
s = " " + s;
for (int i = 1; i <= n; i++)
{
c0[i] = c0[i - 1];
c1[i] = c1[i - 1];
if (s[i] == '1') c1[i]++;
else c0[i]++;
}
for (int len = l+1; len<=n; len++)
{
for (int i = 1; i+len-1<=n; i++)
{
int m = i + len - 1;
for (int j = i; j<=m-1; j++)
{
int C0 = c0[j] - c0[i - 1];
int C1 = c1[m] - c1[j];
if (abs(C0 - C1) >= l && abs(C0 - C1) <= r)
{
dp[i][m] = max(dp[i][m], dp[i][j] + dp[j + 1][m] + 1);
}
}
}
}
cout<<dp[1][n]<<endl;
return 0;
}
标签:01,切割,int,550,2.0,C1,C0
From: https://blog.csdn.net/2301_80443784/article/details/140577291