defminNumberOfSemesters(self,n:int,dependencies:List[List[int]],k:int)->int:fromcollectionsimportdefaultdictdep=defaultdict(int)# 保存当前课程的前置依赖关系for[pre,cur]independencies:dep[cur-1]|=1<<(pre-1)# 满足当前状态的 i, 所需要的最小步数dp=[n]*(1<<n)dp[0]=0foriinrange(1<<n):# 获取当前 i 可以学的前置课程。to_learn=0forjinrange(n):if(1<<j)&i:continueifi&dep[j]==dep[j]:to_learn|=1<<jto_learn&=~is=to_learnwhiles>0:ifbin(s).count("1")<=k:dp[i|s]=min(dp[i|s],dp[i]+1)# s 的二进制包含 1 的子集集合s=(s-1)&to_learn# print(i, ex)returndp[-1]
方案二
此方案主要优化这个子组合的获取。
思路:
1. 获取当前可以学习的课程,将其放置在 list 数组中
2. 判断 list 数组的大小,若其长度小于等于 k 值,则全部学习
3. 若 List 数组的长度大于 k 值,利用 Python 的 itertools 库中的 combination 来获取长度为 k 的组合数。
12345678910111213141516171819202122232425262728
defminNumberOfSemesters(self,n:int,dependencies:List[List[int]],k:int)->int:fromcollectionsimportdefaultdictfromitertoolsimportcombinationsdep=defaultdict(int)# 保存当前课程的前置依赖关系for[pre,cur]independencies:dep[cur-1]|=1<<(pre-1)# 满足当前状态的 i, 所需要的最小步数dp=[n]*(1<<n)dp[0]=0foriinrange(1<<n):to_learn_list=[]forjinrange(n):if(1<<j)&i:continueifi&dep[j]==dep[j]:to_learn_list.append(j)iflen(to_learn_list)<=k:s=0forjinto_learn_list:s|=1<<jdp[i|s]=min(dp[i|s],dp[i]+1)else:forsub_listincombinations(to_learn_list,k):s=0forjinsub_list:s|=1<<jdp[i|s]=min(dp[i|s],dp[i]+1)returndp[-1]