1494. 并行课程 II
难度困难116
给你一个整数 n
表示某所大学里课程的数目,编号为 1
到 n
,数组 relations
中, relations[i] = [xi, yi]
表示一个先修课的关系,也就是课程 xi
必须在课程 yi
之前上。同时你还有一个整数 k
。
在一个学期中,你 最多 可以同时上 k
门课,前提是这些课的先修课在之前的学期里已经上过了。
请你返回上完所有课最少需要多少个学期。题目保证一定存在一种上完所有课的方式。
示例 1:
输入:n = 4, relations = [[2,1],[3,1],[1,4]], k = 2
输出:3
解释:上图展示了题目输入的图。在第一个学期中,我们可以上课程 2 和课程 3 。然后第二个学期上课程 1 ,第三个学期上课程 4 。
示例 2:
输入:n = 5, relations = [[2,1],[3,1],[4,1],[1,5]], k = 2
输出:4
解释:上图展示了题目输入的图。一个最优方案是:第一学期上课程 2 和 3,第二学期上课程 4 ,第三学期上课程 1 ,第四学期上课程 5 。
示例 3:
输入:n = 11, relations = [], k = 2
输出:6
提示:
1 <= n <= 15
1 <= k <= n
0 <= relations.length <= n * (n-1) / 2
relations[i].length == 2
1 <= xi, yi <= n
xi != yi
- 所有先修关系都是不同的,也就是说
relations[i] != relations[j]
。 - 题目输入的图是个有向无环图。
状态压缩DP
https://leetcode.cn/problems/parallel-courses-ii/solution/yu-niang-niang-1494-bing-xing-ke-cheng-i-duny/
为什么这题不能用拓扑排序?
这个图,实际最佳出队方式是:[7,8],[1,2],[3,4][5,6],[9,10]
只需要5次,因此拓扑不能用
方法:状压DP
-
因为点编号是1到n,所以对应于0到n-1的数组,映射位置应为 i-1
-
使用状压代表课程先修
-
枚举学习课程的已经学习情况
-
枚举当前学习情况,后续可学习的可能情况
-
枚举当前1的位置的子集(包含自身),然后用 当前课程= (当前课程-1)&所有可学课程 ,这种方式,循环找到所有课程枚举子集
细节
-
枚举可学课程需要排除已学课程
-
枚举选择的本轮课程需要排除掉一轮学习可能超过最大目标课程的情况
class Solution {
public int minNumberOfSemesters(int n, int[][] relations, int k) {
int[] pre = new int[n];
for(int[] re : relations){
//1. 因为点编号是1到n,所以对应于0到n-1的数组,映射位置应为 i-1
//2. 使用状压代表课程先修
pre[re[1] - 1] |= 1 << (re[0] - 1);
}
int max = 1 << n;
int[] dp = new int[max];
Arrays.fill(dp, n);
dp[0] = 0;
//3. 枚举学习课程的已经学习情况
for(int learned = 0; learned < max; learned++){
//4. 枚举当前学习情况,后续可学习的可能情况
int waitStudy = 0;
for(int i = 0; i < n; i++){
if((pre[i] & learned) == pre[i]){
waitStudy |= 1 << i;
}
}
//细节1. 枚举可学课程需要排除已学课程
waitStudy = waitStudy & (~learned);
//5. 枚举当前1的位置的子集(包含自身),然后用 当前课程= (当前课程-1)&所有可学课程,
// 这种方式,循环找到所有课程枚举子集
for(int learnTerm = waitStudy; learnTerm > 0; learnTerm = (learnTerm-1)& waitStudy){
//细节2. 枚举选择的本轮课程需要排除掉一轮学习可能超过最大目标课程的情况
if(Integer.bitCount(learnTerm) > k)
continue;
dp[learned|learnTerm] = Math.min(dp[learned|learnTerm],dp[learned]+1);
}
}
return dp[max-1];
}
}
相似题目(状压 DP)
https://leetcode.cn/problems/parallel-courses-ii/solution/zi-ji-zhuang-ya-dpcong-ji-yi-hua-sou-suo-oxwd/
- 1879. 两个数组最小的异或值之和
- 2172. 数组的最大与和
- 1125. 最小的必要团队,题解
- 1986. 完成任务的最少工作时间段