牛客小白月赛--切割01串 2.0

题目来源

点击跳转牛客🐂

题目分析

在这里插入图片描述
 题目的意思就是求出最大的切割次数是多少,切割的条件图片中描述的很清楚。就是切割的左部分的0的个数与右部分1的个数的差值的绝对值要在 [ L , R ] [L,R] [L,R]之间。

思路

  一开始是想着用贪心的方法来写,但是没有写出来,贪心不能够将所有的条件都给考虑到。因为切割之后的串还可以继续进行操作。大部分可以生出小部分。这就符合DP的思想。虽然当时感觉DP是正解,但是状态转移方程不会写,一点DP的思路都没有。
这是一个线性DP的题。我们设 f [ L ] [ R ] f[L][R] f[L][R]代表的意思是从L到R的最大切割次数。
 之后来推状态转移方程,我们发现在L到R之间如果有一个K将这一段分成两段,并且又正好符合切割条件,那么 f [ L ] [ R ] = f [ L ] [ K ] + f [ K + 1 ] [ R ] + 1 f[L][R]=f[L][K]+f[K+1][R]+1 f[L][R]=f[L][K]+f[K+1][R]+1,我们用一重循环来循环L的值,用一重循环来循环R的值,再用一重循环来循环K的值,然后要想判断是否符合题目中的条件就要每次循环找一下0和1的个数,我们这里如果再开一重循环就是 n 4 n^4 n4,一定会超时的,所以我们用前缀和预处理一下。就能将 n 4 n^4 n4降为 n 3 n^3 n3
         下面看一下代码

代码

int a[1050],b[1050];
void solve () {
	int n,l,r;cin>>n>>l>>r;
	string s;cin>>s;s = " "+s;
	for (int i=1;i<=n;i++) {
		a[i]=a[i-1]+(s[i]=='1');
		b[i]=b[i-1]+(s[i]=='0');
	}
	for (int i=1;i<=n;i++) {
		for (int q=1;q+i-1<=n;q++) {
			int w=q+i-1;
			for (int k=q;k<=w-1;k++) {
				int x=b[k]-b[q-1];
				int y=a[w]-a[k];
				if (abs(x-y)>=l&&abs(x-y)<=r) 
				f[q][w]=max(f[q][w],f[q][k]+f[k+1][w]+1);
			}
		}
	}
	cout<<f[1][n]<<'\n';
}

总结

 感觉是一道比较好的线性DP的题,不是很简单感觉。感觉对于没怎么学过动态规划的人来说,这一题还是比较难的,只能多刷刷题,早日能自己写出来这种题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值