10817 - Headmaster's Headache

来源:互联网 发布:2000年人口普查数据 编辑:程序博客网 时间:2024/04/27 00:31

Problem D: Headmaster’s Headache

Time limit: 2 seconds

The headmaster of Spring Field School is considering employing some new teachers for certain subjects. There are a number of teachers applying for the posts. Each teacher is able to teach one or more subjects. The headmaster wants to select applicants so that each subject is taught by at least two teachers, and the overall cost is minimized.

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

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
Problemsetter: Mak Yan Kei
Idea from “Linear Optimization in Applications”, S. L. Tang, Hong Kong University Press, 1999

问题D:校长头痛
期限:2秒
春季田间学校的校长正在考虑采用一些新教师对某些科目。有许多老师申请职位。每个老师可以教一个或多个主题。校长想选择申请人,以便每个主题由至少两个老师教,和整体成本最小化。
输入
输入包含多个测试用例。他们每个人的格式说明如下:
第一行包含三个正整数,M和N(≤8)是对象的数量,(≤20)是为教师服务的数量,和N(≤100)申请者的数量。
下面的M文件中的每一行描述一个老师。它首先给使用他/她的成本(10000 C≤≤50000),紧随其后的是一个科目列表,他/她可以教。受试者编号从1到M的在职教师不能辞退。后有N行,为新老师的情况。
输入由空终止情况S = 0。这种情况下不应该处理。
输出
对于每一个测试用例,给出约束条件下的最小成本雇佣老师。
样例输入
2 2 2
10000年1
20000 2
30000 1 2
40000 1 2
0 0 0
样例输出
60000
Problemsetter:Mak燕祺
线性优化理念从“应用程序”,s . l .唐、香港大学出版社,1999年

我有话说:
这道题的一种思路是状态压缩DP。因为只有8个科目,所以可以用二进制数来表示该科目是否有人教。然后按编号对0到m-1的教师考虑。
状态转移方程:dp(i,s0,s1,s2)=min{dp(i,s0,s1,s2),c[i]+dp(i+1,s0’,s1’,s2’));
i表示序号0-i-1的人已经决策了。s0表示目前没有人教的科目,s1表示目前只有一个人教的科目,s2表示目前有两个人教的科目。s0,s1,s2均转化为2进制数表示。s1,s2中1表示有人教,s0中1表示没有人教。

#include <iostream>#include <cstdio>#include <algorithm>#include <sstream>#include <cstring>using namespace std;const int maxn = 100 + 20 + 5;const int maxs = 8;const int INF = 1000000000;int m, n, s, c[maxn], st[maxn], d[maxn][1<<maxs][1<<maxs];//i表示序号0-i-1的人已经决策了。s0表示目前没有人教的科目,s1表示目前只有一个人教的科目,s2表示目前有两个人教的科目。s0,s1,s2均用2进制数表示。1表示有人教int dp(int i,int s0,int s1,int s2){    if(i==n+m)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;//^异或:相同为0,不同为1;    ans=min(ans,dp(i+1,s0,s1,s2)+c[i]);    return ans;}int main(){    string line;    while(getline(cin,line))    {        stringstream ss(line);        ss>>s>>m>>n;        if(s==0)break;        for(int i=0;i<n+m;i++)        {            int x;            getline(cin,line);            stringstream ss(line);            ss>>c[i];            st[i]=0;            while(ss>>x)st[i]|=(1<<(x-1));        }        memset(d,-1,sizeof(d));        cout<<dp(0,(1<<s)-1,0,0)<<endl;    }    return 0;}
0 0