蓝桥杯练习5——小蓝的零花钱

问题描述

小蓝和小桥正在玩一个游戏,他们有一个长度为 nn 的序列,其中既有偶数也有奇数,且偶数和奇数的数量相等。

小蓝有一些零花钱,他可以用这些钱来做一个特殊的操作:他在序列中选取一个位置,然后在这个位置上将序列分成两段,要求每一段中偶数和奇数的数量都相等。小蓝想要用他的零花钱尽可能多地进行这个操作,但每次操作都需要花费代价。具体而言,每次选取的位置可以看成是对序列进行切割,切割需要花费的代价为切割两端的元素的差的绝对值。小蓝想知道,在他的预算范围内,最多能进行多少次操作。

请你帮助小蓝计算最多可以进行的操作次数。

输入格式

第一行包含两个整数 nn 和 BB(2≤n≤100,1≤B≤1002≤n≤100,1≤B≤100),表示序列的长度和小蓝拥有的零花钱数。

第二行包含 nn 个整数 a1,a2,⋯,ana1​,a2​,⋯,an​(1≤ai≤1001≤ai​≤100),表示给定的序列(保证在这 nn 个元素中奇数的个数等于偶数的个数)。

输出格式

输出一个整数,表示在小蓝的预算范围内,能够进行的最多操作次数。

输入:

6 3

1 2 3 4 5 6

输出:

2

思路:

题目要求是将序列分割成若干份且每段中奇数和偶数的数量相同。每次分割的代价就是分割点两端元素的差的绝对值。目标是在预算的范围中进行尽可能多的分割。因此代码分三部分:①统计奇偶性:通过遍历序列,统计奇数和偶数的差值(sum),当差值为0时说明当前端奇偶数量相同,可以分割。②记录代价:将每个可能的分割点的代价记录下来(cnt数组)③贪心选择:将代价从小到大排序,尽可能选择代价小的分割点,直到预算用完。

动态规划和贪心的区别:

动态规划通常用于解决具有重叠子问题和最优子结构问题,通过保存中间结果来避免重复计算;贪心算法每一步都做出局部最优选择,希望最终结果也是全局最优。

t = 1
ans = []
#预算范围中的操作次数
for _  in range(t):
  n,B = map(int,input().split())
  a = list(map(int,input().split()))
  sum = 0
  #奇偶数的差值
  cnt = []
  #分割点的代价
  for i in range(n):
    if a[i] & 1:
      #奇数的二进制表示最后一位都是1 用于快速判断是否为奇数
      sum += 1
    else:
      sum -= 1
      if sum == 0 and i + 1 < n:#要考虑不要越界
        cnt.append(abs(a[i+1]-a[i]))
  cnt.sort()
  ans = 0
  #将得到的分割点计算代价 在B的范围内
  for c in cnt:
    if B >= c:
      B -= c
      ans += 1
    else:
      break
  print(ans)

在给的事例中奇数个数等于偶数个数所以存在分割点。遍历序列后,1(奇数):sum = 1;2(偶数):sum = 0且i+1<n,即i=1,下一个元素为3,以此类推.....最终1到6的最终i=5,已到序列结尾不做处理,得到的代价cnt = [1,1];在 `2` 和 `3` 之间分割,代价为 `1`,分割后的子序列为 `[1, 2]` 和 `[3, 4, 5, 6]`。在 `4` 和 `5` 之间分割,代价为 `1`,分割后的子序列为 `[3, 4]` 和 `[5, 6]`。最后在预算范围内选择分割点:初始化Answer= 0,B=3,遍历cnt列表[1,1]:第一个代价 `1`:B >= 1,执行操作,B -= 1,ans += 1,此时 B = 2,ans = 1。  第二个代价 `1`:B >= 1,执行操作,B -= 1,ans += 1,此时 B = 1,`ans = 2。 由于 `cnt` 列表已经遍历完毕,最终 ans = 2。

 

                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值