python: 2020算法笔试题目-假期

由于业绩优秀,公司给小Q放了 n 天的假,身为工作狂的小Q打算在在假期中工作、锻炼或者休息。他有个奇怪的习惯:不会连续两天工作或锻炼。只有当公司营业时,小Q才能去工作,只有当健身房营业时,小Q才能去健身,小Q一天只能干一件事。给出假期中公司,健身房的营业情况,求小Q最少需要休息几天。

输入描述:
第一行一个整数 表示放假天数
第二行 n 个数 每个数为0或1,第 i 个数表示公司在第 i 天是否营业
第三行 n 个数 每个数为0或1,第 i 个数表示健身房在第 i 天是否营业
(1为营业 0为不营业)

输出描述:
一个整数,表示小Q休息的最少天数

输入例子1:
4
1 1 0 0
0 1 1 0

输出例子1:
2

例子说明1:
小Q可以在第一天工作,第二天或第三天健身,小Q最少休息2天

============================================================================
算法思路

题目中的工作、锻炼和休息可以看作三种状态,每天做的事情,就是在状态间转移,有如下状态转移关系(其中工作和锻炼的下一个状态不能使自己,休息可以回到自己):
在这里插入图片描述
因为,下一个状态总是只和前一状态相关。
我们做如下假设,设a是截止至橙色区域最大非休息天数,b是截止至绿色区域最大非休息天数,现依据a和b推算灰色区域的最大非休息天数c,若有f(a,b,x,y)=c,则,f(b,c,x,y)=d。
我们根据a、b、x、y推算出下一个最大非休息天数c,则进一步可以根据b、c、x、y,以此类推,可迭代出最大非休息天数。(也就是每一次都保留,目前的最大非休息天数和上一次的最大非休息天数)
在这里插入图片描述
根据以上假设,我们可以做如下推演,我们假设b最后落在状态“锻炼”上,用状态“工作”去承接a。
1、对于(0,0)的情形
(1)假设初始状态在“工作”,他只能转移至“锻炼”,那么a就要向下加上0,由于“锻炼”是0,所以最大的非休息天数保持不变,仍然是a,同时这个数值要赋予“锻炼”,因为状态已经转移
(2)假设初始状态在“锻炼”,他只能转移至“工作”,那么b就要向上加上0,由于“工作”是0,所以最大的非休息天数保持不变,仍然是b,同时这个数值要赋予“工作”,因为状态已经转移
2、对于(1,0)的情形
(1)假设初始状态在“工作”,他只能转移至“锻炼”,那么a就要向下加上1,由于“锻炼”是1,可以锻炼,因此最大的非休息天数就变为a+1;但如果a+1小于b,意味着选择状态“工作”作为初始状态是不好的(因为我们直接选择“锻炼”作为初始状态,下一步是休息,因为“工作”是0,得到的最大非休息天数就是b,比a+1好),可以直接保留b。那么对于以“锻炼”为初始状态的情形,我们把前一步的最大非休天数max(a,b)保留下来即可。
3、其他情形以此类推
最终我们可以整合四种情形旧的非休数组(a,b),被x、y更新为(max(a,b+x), max(b,a+y))。
在这里插入图片描述
下面这个图可以帮助进一步理解,假设max(a,b+x)< max(b,a+y),我们又得到新的一组a和b,以此类推,最终得到最大的非休天数,。
在这里插入图片描述
Python代码如下:

'''
#笔试格式
n = int(input())
work = list(map(lambda x:int(x), input().split()))
exercise = list(map(lambda x:int(x), input().split()))
'''
#生成模拟数组
import numpy as np
n = 100000
np.random.seed(5); a = list(np.random.randint(0, 2, n))
np.random.seed(6); b = list(np.random.randint(0, 2, n))
#算法代码
dp = [[0] * (n + 1), [0] * (n + 1)]
for i in range(1, n + 1):
    dp[0][i] = max(a[i-1] + dp[1][i - 1], dp[0][i - 1])
    dp[1][i] = max(b[i-1] + dp[0][i - 1], dp[1][i - 1])
print(n - max(dp[0][n], dp[1][n]))

发布了20 篇原创文章 · 获赞 3 · 访问量 1487

猜你喜欢

转载自blog.csdn.net/qq_42830966/article/details/105399320
今日推荐