Time Limit: 4500 mSec
Problem Description
Input
The input consists of several test cases. The format of each of them is explained below: The first line contains three positive integers S, M and N. S (≤ 8) is the number of subjects, M( ≤ 20) is the number of serving teachers, and N (≤ 100) is the number of applicants. Each of the following M lines describes a serving teacher. It first gives the cost of employing him/her (10000 ≤ C ≤ 50000), followed by a list of subjects that he/she can teach. The subjects are numbered from 1 to S. You must keep on employing all of them. After that there are N lines, giving the details of the applicants in the same format. Input is terminated by a null case where S = 0. This case should not be processed.
Output
Sample Input
Sample Output
60000
题解:状压dp,但是比较麻烦的地方在于不少于2人,因此最直接的想法就是三进制枚举,不过三进制写起来有些麻烦,转念一想,其实可以用两个二进制位来代替这个三进制,我的两个二进制位的状态定义其实有些问题,比较正的思路就是前八位和后八位分别代表一个和大于等于两个。我的代码是跟着lrj的思路做的,实现的思路还是很好的,三进制可以转成两个二进制,用两个集合来表示整个状态,很值得学习(好写嘛),状态定义为dp[i][s1][s2],表示考虑到前i个人,在状态(s1,s2)之下到达目标状态还要花费多少。这样方程就很好写了。在转移状态的时候需要位运算,这个硬想是很困难的,画个图就很简单了,交,并,对称差分别对应&,|,^。
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 const int maxs = 10, maxm = 25, maxn = 105; 6 const int INF = 1e9; 7 8 int s, m, n; 9 int cost[maxn + maxm], teach[maxn + maxm]; 10 int dp[maxm + maxn][1 << maxs][1 << maxs]; 11 12 int DP(int i, int s0, int s1, int s2) { 13 if (i == m + n) return s2 == (1 << s) - 1 ? 0 : INF; 14 int& ans = dp[i][s1][s2]; 15 if (ans >= 0) return ans; 16 17 ans = INF; 18 if (i >= m) ans = DP(i + 1, s0, s1, s2); 19 20 int t0 = s0 & teach[i]; //new subjects 21 int t1 = s1 & teach[i]; 22 s0 ^= t0; s1 = (s1^t1) | t0; s2 |= t1; 23 ans = min(ans, DP(i + 1, s0, s1, s2) + cost[i]); 24 return ans; 25 } 26 27 int main() 28 { 29 //freopen("input.txt", "r", stdin); 30 string str; 31 while (getline(cin, str)) { 32 stringstream ss(str); 33 ss >> s >> m >> n; 34 if (s == 0) break; 35 memset(teach, 0, sizeof(teach)); 36 memset(dp, -1, sizeof(dp)); 37 for (int i = 0; i < n + m; i++) { 38 getline(cin, str); 39 stringstream ss(str); 40 ss >> cost[i]; 41 int t; 42 while (ss >> t) { 43 t--; 44 teach[i] |= (1 << t); 45 } 46 } 47 printf("%d ", DP(0, (1 << s) - 1, 0, 0)); 48 } 49 return 0; 50 }