#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cstdlib>
#include <string>
#include <vector>
#include <cstdio>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
using namespace std;
#define INF 0x3f3f3f3f
const int N=200005;
const int mod=1e9+7;
int n,m,s,c[125],st[125],d[125][1<<10][1<<10];
int dp(int i,int s0,int s1,int s2) {
if (i==m+n) return s2==(1<<s)-1?0:INF;
int& ans=d[i][s1][s2];
if (ans>=0) return ans;
ans=INF;
if (i>=m) ans=dp(i+1, s0, s1, s2);
int m0=st[i]&s0,m1=st[i]&s1;
s0^=m0;
s1=(s1^m1)|m0;
s2|=m1;
ans=min(ans,c[i]+dp(i+1, s0, s1, s2));
return ans;
}
int main() {
char t[30];
while (cin>>s>>m>>n&&s) {
memset(st, 0, sizeof(st));
memset(d, -1, sizeof(d));
memset(c, 0, sizeof(c));
getchar();
for (int i=0; i<n+m; i++) {
memset(t, 0, sizeof(t));
gets(t);
c[i]=(t[0]-'0')*1e4+(t[1]-'0')*1e3+(t[2]-'0')*1e2+(t[3]-'0')*10+(t[4]-'0');
for (int j=5; j<30; j++) {
if (t[j]>'0'&&t[j]<='9') {
st[i]|=1<<(t[j]-'1');
}
}
}
cout<<dp(0, (1<<s)-1, 0, 0)<<endl;
}
return 0;
}
Headmaster's Headache
The headmaster of SpringField School is consider-ing employing some newteachers for certain subjects.There are a number of teach-ers applying for the posts.Each teacher is able to teachone or more sub jects. Theheadmaster wants to selectapplicants so that each sub-ject is taught by at least twoteachers, and the overall costis minimized.
Input
The input consists of severaltest cases. The format ofeach of them is explained below:
The first line contains three positive integersS,M andN.S (≤8) is the number of subjects, M(≤20) is the number of serving teachers, andN (≤100) is the number of applicants.
Each of the following Mlines 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 numberedfrom 1 toS.You must keep on employing all of them. After that there are Nlines, giving thedetails of the applicants in the same format.
Input is terminated by a null case where S = 0. This case should not be processed.
Output
For each test case, give the minimum cost to employ the teachers under the constraints.
Sample Input
2 2 2
10000 1
20000 2
30000 1 2
40000 1 2
0 0 0
Sample Output
60000
题意:
某校有m个教师和n个求职者,需讲授s个课程,已知每人的工资c和能教的课程集合,要求支付最少的工资使得每门课都至少有两名教师能教。在职教师不能辞退。
分析:
本题用到了子集的二进制表示,之前书上看得已经忘了……紫书上又提一遍,这次好好学习一下。
其实内容很简单,如果集合里有n个元素,则(1<<n)-1的值等于二进制形式下1-n位的所有位均为1,如果集合含有第i个元素,则第i位为1即可。要熟练掌握|与&等基础位运算。
本题用s1表示恰好一个人教的科目集合,s2表示至少有两个人教的科目集合,d(i,s1,s2)表示已经考虑了前i个人时的最小花费。
状态转移方程d(i,s1,s2)=min{d(i+1,s1',s2')+c[i],d(i+1,s1,s2)} (选与不选)
老师必须聘用,i<m时必只能取第一项。
最终结果输出dp(0,(1<<s)-1,0,0),因为初始没人教课。
如果能够掌握这里的二进制表示方法,其实是简单的dp题。