Info
// https://leetcode.com/problems/parallel-courses-ii/description/
#include <bit>
#include <cstdint>
#include <iostream>
#include <optional>
#include <print>
#include <utility>
#include <vector>
template<typename Callback>
void iterateKSetBits(uint64_t bitMask, int k, Callback&& callback) {
uint32_t subMask = 0;
while (k--) {
subMask |= std::bit_floor(bitMask ^ subMask);
}
auto prevStart = subMask;
while (true) {
callback(subMask);
if (bitMask == subMask) {
return;
}
auto a = (subMask & -subMask);
auto b = std::bit_floor(bitMask & (a - 1));
if (b) {
subMask ^= a ^ b;
} else {
auto c = std::bit_floor(bitMask);
bitMask ^= c;
subMask = prevStart ^ c;
subMask |= std::bit_floor(bitMask ^ subMask);
prevStart = subMask;
}
}
}
template<typename Callback>
void iterateSetBits(uint64_t bitMask, Callback&& callback) {
while (bitMask) {
auto setBit = bitMask & -bitMask;
callback(setBit);
bitMask ^= setBit;
}
}
int parallelCourses2(int n, std::vector<std::vector<int>> const& relations, int k) {
auto dp = std::vector<std::optional<int>>(1 << n, std::nullopt);
std::vector<int> prerequisites(n, 0);
for (auto const& relation: relations) {
prerequisites[relation[1] - 1] |= (1 << (relation[0] - 1));
}
auto dpFunc = [n = n, k = k, &dp = dp, &prerequisites = std::as_const(prerequisites)](this auto&& dpFunc, int coursesTaken) -> int {
std::println("called | coursesTaken: {:0{}b}", coursesTaken, n);
auto& dpVal = dp[coursesTaken];
if (dpVal) {
std::println("done | coursesTaken: {:0{}b} | dpVal: {}", coursesTaken, n, *dpVal);
return *dpVal;
}
if (coursesTaken == (1 << n) - 1) {
dpVal = 0;
std::println("done | coursesTaken: {:0{}b} | dpVal: {}", coursesTaken, n, *dpVal);
return *dpVal;
}
uint64_t nextCourses = 0;
iterateSetBits(((uint64_t(1) << n) - 1) ^ coursesTaken, [&](auto const& notTakenCourseMask) {
auto notTakenCourse = std::countr_zero(notTakenCourseMask);
if ((coursesTaken & prerequisites[notTakenCourse]) == prerequisites[notTakenCourse]) {
nextCourses |= (1 << notTakenCourse);
}
});
iterateKSetBits(nextCourses, k, [&](auto const& subMask) {
auto minSemesters = 1 + dpFunc(coursesTaken ^ subMask);
if (dpVal) {
dpVal = std::min(*dpVal, minSemesters);
} else {
dpVal = minSemesters;
}
});
if (dpVal) {
std::println("done | coursesTaken: {:0{}b} | dpVal: {}", coursesTaken, n, *dpVal);
return *dpVal;
}
std::println("done | coursesTaken: {:0{}b} | dpVal: {}", coursesTaken, n, *dpVal);
return *dpVal;
};
return dpFunc(0);
}
int main() {
{
auto minSemesters = parallelCourses2(4, {{2, 1}, {3, 1}, {1, 4}}, 2);
std::println("minSemesters: {}", minSemesters);
}
{
auto minSemesters = parallelCourses2(5, {{2, 1}, {3, 1}, {4, 1}, {1, 5}}, 2);
std::println("minSemesters: {}", minSemesters);
}
}