2019.10.27日常总结兼onecode CSP-J DP题目A题解

【题目A】:

【题目】:
有很多东西是可以被切割的,比如——树、纸张或者绳子。在这道题目里面你需要切割一个整数序列。
现在告诉你一个整数序列,在这个整数序列里面有一些数,它们可能是奇数,也可能是偶数。
给你一个固定的预算(因为切割是有成本的),你需要竟可能多地将这个整数序列切分成一系列连续子序列,
使得每一个连续子序列中的 奇数元素的个数 和 偶数元素的个数 相同。
比如,给你一个整数序列 [ 4 , 1 , 2 , 3 , 4 , 5 , 4 , 4 , 5 , 5 ] [4,1,2,3,4,5,4,4,5,5] [4,1,2,3,4,5,4,4,5,5] ,你可以将其切割两次变成 [ 4 , 1 ∣ 2 , 3 , 4 , 5 ∣ 4 , 4 , 5 , 5 ] [4,1 | 2,3,4,5 | 4,4,5,5] [4,12,3,4,54,4,5,5] 。其中, [ 4 , 1 ] [4,1] [4,1] [ 2 , 3 , 4 , 5 ] [2,3,4,5] [2,3,4,5] 以及 [ 4 , 4 , 5 , 5 ] [4,4,5,5] [4,4,5,5] 这三个连续子序列中包含的奇数个数等于偶数个数。
如果你要将第 i i i 个元素和第 i + 1 i+1 i+1 个元素之间切一刀,我们假设第 i i i 个元素对应的数值为 x x x ,第 i + 1 i+1 i+1 个元素对应的数值为 y y y ,那么你需要消耗 ∣ x − y ∣ |x-y| xy 个比特币。( ∣ x − y ∣ |x-y| xy 表示 x − y x-y xy 的差的绝对值)。
而你的预算只有 B B B 个比特币,所以你需要计算一下在最多消耗 B B B 个比特币的情况下,你最多可以切几次。
【思路】: f i , k f_{i,k} fi,k表示前 i i i个数且有 k k k个比特币时最多可以切割多少刀。所以我们可以得到如下的 d p dp dp方程: f i , k = f j , k − ∣ a j − a j − 1 ∣ + 1 f_{i,k}=f_{j,k-|a_j-a_{j-1}|}+1 fi,k=fj,kajaj1+1,其中 j < i , k ≥ ∣ a j − a j − 1 ∣ j<i,k\geq |a_j-a_{j-1}| j<i,kajaj1,且区间 [ i , j ] [i,j] [i,j]中奇数个数等于偶数个数。而奇数个数和偶数个数可以用前缀和求出。根据定义,答案即为 f n , B f_{n,B} fn,B
【代码】:

#include <bits/stdc++.h>
using namespace std;
int f[110][110],a[110];
int i,j,k,n,B,s[2][110];
int main(){
//	freopen("t1.in","r",stdin);
	scanf("%d%d",&n,&B);
	for(i=1;i<=n;i++){
		scanf("%d",&a[i]);
		s[a[i]%2][i]=s[a[i]%2][i-1]+1;
	}
	for(i=2;i<=n;i++)
		for(j=1;j<i;j++)
			if (s[0][i]-s[0][j-1]==s[1][i]-s[1][j-1])
				for(k=abs(a[j]-a[j-1]);k<=B;k++)
					f[i][k]=max(f[i][k],f[j-1][k-abs(a[j-1]-a[j])]+1);
	printf("%d",f[n][B]);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值