#include <iostream> #include <bitset> #include <algorithm> #include <conio.h> #define MAX_N 12 #define MAX_M 10 using namespace std; int INF = 987654321; int N, K, M, L; int before[MAX_N][MAX_N]; int semesters[MAX_M][MAX_N]; int cache[10][1 << MAX_N]; unsigned int beforeBit[MAX_N]; unsigned int semBit[MAX_M]; int graduate(int semester, int taken); int main() { int caseNum; int beforeNum; int semNum; cin >> caseNum; for (int cIter = 0; cIter < caseNum; cIter++) { cin >> N >> K >> M >> L; #pragma region Input for (int i = 0; i < N; i++) { beforeBit[i] = 0; cin >> beforeNum; if (beforeNum == 0) { beforeBit[i] = 0; } else { for (int j = 0; j < beforeNum; j++) { cin >> before[i][j]; beforeBit[i] |= 1u << before[i][j]; } } } for (int i = 0; i < M; i++) { semBit[i] = 0; cin >> semNum; if (semNum == 0) { semBit[i] = 0; } else { for (int j = 0; j < semNum; j++) { cin >> semesters[i][j]; semBit[i] |= 1u << semesters[i][j]; } } } #pragma endregion // Initialize for (int i = 0; i < 10; i++) for (int j = 0; j < (1 << MAX_N); j++) cache[i][j] = -1; // Process int minSem = graduate(0, 0); // Output if (minSem == INF) cout << "IMPOSSIBLE" << endl; else cout << minSem << endl; } _getch(); } int graduate(int semester, int taken) { if (bitset<32>(taken).count() >= K) return 0; if (semester == M) return INF; int& ret = cache[semester][taken]; if (ret != -1) return ret; ret = INF; int canTake = (semBit[semester] & ~taken); for (int i = 0; i < N; i++) if ((canTake & (1 << i)) && (taken & beforeBit[i]) != beforeBit[i]) canTake &= ~(1 << i); for (int take = canTake; take > 0; take = ((take - 1) & canTake)) { if (bitset<32>(take).count() > L) continue; ret = min(ret, graduate(semester + 1, taken | take) + 1); } ret = min(ret, graduate(semester + 1, taken)); return ret; }
반응형