Headmaster's Headache

he 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 SM and NS (≤ 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 SYou 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

题目大意:某校有n个教师和m个求职者。已知每人的工资和能交的课程集合,要求支付最少的工资使得每门课都至少有两名教师教学。在职教师必须招聘

输入格式:每组数据的第一行为3个整数s、m和n(1<=s<=8,1<=m<=20,1<=n<=100),即科目的个数、在职教师个数和申请者个数:以下m行每行用一些整数描述一位在职教师,其中第一个整数c(1000<=c<=50000)是工资,接下来的若干整数是他能教的科目列表(课程编号为1~s之间的整数);接下来的n行描述申请者,格式同上。输入结束标志为s=0.
输出格式:对于每组数据,输出工资总额的最小值。 分析:
  每一个老师可以教多门课程,而且在职教师必须招聘,那么在职教师能教的课就应该全部教,假设他们教的课程达到状态st。那么答案就是
          所有在职教师的工资+(完成最终状态-st状态)的所有求职工的工资   科目个数最多为8,用16位2进制数来表示。2进制中从右往左数,前8为表示有1位老师教该门课程,后8为表示有2位老师教(该位-8)的课程,当s=8时,00000010 00000001表示1个老师教第一门课,2个老师教第2门课。这样 11111111 00000000 即为所要求的目标状态,代码中用T表示。   令dp[i][j]表示在前 j 个求职工中达到状态 i的最小花费。用st表示当前状态,则
      dp[i][j] = min{dp[i][j], dp[i][j+1], dp[i+第j个人能够教的科目][j+1] +第j个人的工资}   定义函数int DP(int st,int i)表示第i个人开始到n个人结束,从状态 st 开始到目标状态的最小花费。这里用到记忆化搜索。
  题目中没有给出每个老师会教的课程的数目,而是直接给课程的编号,所以要用gets输入,用sscanf提取其中的数字,这里我用动态二维数组保存每个求职者能教的课程。
    sscanf(*s,"%d",&y)表示从字符串s中取出第一个数字,并且保存在y中
    isdigit()判断字符c是否是数字,当字符c我0-9时返回非0值,否则返回0。
   for(j=0;j<strlen(t);j++){
      sscanf(t+j,"%d",&y);
      for(;isdigit(t[j]);j++);
      j++;
  }
 比如对于一字符串t[]=“1 2 3 4”,先取出数字1,之后j是数字跳过,再往后从t+2开始,取出数字2...
  
代码如下:
 # include<iostream>
# include<cstdio>
# include<cstring>
# include<vector>
# include<cctype> //isdigit()函数包含在ctype.h头文件中
# define INF 0x3f3f3f3f
# define N (<<)+
using namespace std; int min(int a,int b){
return a<b ? a : b;
} int s,m,n,st,T;
bool vis[N][]; //记忆化搜索的标记
int dp[N][];
int v[]; //n位求职者的工资
vector<int>lesson[]; //lesson[i][]表示第i个求职者会教科目的集合 int DP(int st,int i){ if(vis[st][i])
return dp[st][i];
vis[st][i] = true; if(st==T)
return dp[st][i]=;
if(i==n)
return INF;
int next=st; int len=lesson[i].size(); //第i个求职者会教科目的总数
for(int j=;j<len;j++){
int y=lesson[i][j];
if(<<(s+y) & next) //如果已经有2位老师教该课程
continue;
if((<<y) & next) //如果已经有1位老师教该课程
next = next-(<<y)+(<<(s+y));
else //如果没有老师教该课程
next = next + (<<y);
}
if(next != st)
dp[st][i] = min(dp[st][i],DP(next,i+)+v[i]);
dp[st][i] = min(dp[st][i],DP(st,i+));
return dp[st][i];
} int main(){
int i,j,x,y;
char t[]; //临时用来保存老师会教科目的集合,因为没有给出这个集合中元素的个数,所以要用gets输入
while(scanf("%d%d%d",&s,&m,&n) && s)
{
int ans = ; //保存结果
st = ; //表示在职教师能够教的课程的集合
memset(vis,,sizeof(vis)); //初始化
memset(dp,INF,sizeof(dp));
for(i=;i<m;i++) //在职教师
{
scanf("%d",&x);
ans += x; //因为在职教师必须招聘
gets(t);
int k =strlen(t);
for(j=;j<k;j++){
sscanf(t+j,"%d",&y); //用sscanf提取工资后面的数组,y就是该教师所会的科目
y--; //只是将1~8门课程变成0~7门课程,便于2进制运算
for(;isdigit(t[j]);j++); //跳过是数字的字符
j++; //那么往前走一步,下一次就能取到下一个数字了
if(<<(s+y)&st)
continue;
if(<<y&st)
st = st-(<<y)+(<<(s+y));
else
st = st+(<<y);
}
}
for(i=;i<n;i++) lesson[i].clear();
for(i=;i<n;i++){
scanf("%d",&v[i]);
gets(t);
int k = strlen(t);
for(j=;j<k;j++){
sscanf(t+j,"%d",&y);
lesson[i].push_back(y-);
for(;isdigit(t[j]);j++); //跳过是数字的字符
j++;
}
}
T = ; //需要达成的状态
for(i=s;i<*s;i++)
T += (<<i); printf("%d\n",ans+DP(st,));
}
return ;
}

好辛苦啊,为了看懂用了3个小时。。。不过还有疑问,为什么INF要在0x3f3f3f3f这个范围左右,改成其他的就不对了

 

UVA 10817 Headmaster's Headache(DP +状态压缩)的更多相关文章

  1. 状压DP UVA 10817 Headmaster's Headache

    题目传送门 /* 题意:学校有在任的老师和应聘的老师,选择一些应聘老师,使得每门科目至少两个老师教,问最少花费多少 状压DP:一看到数据那么小,肯定是状压了.这个状态不好想,dp[s1][s2]表示s ...

  2. UVA 10817 - Headmaster's Headache(三进制状压dp)

    题目:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=20&pag ...

  3. UVA - 10817 Headmaster's Headache

    题目大意:有一些老师,每一位都有自己的工资以及教授的课程.共s<=8个课程.其中的一些老师必须选择,问你保证每节课至少有一个老师的最少总工资. 题解: 首先很容易想到状态压缩,搞一个3进制的数, ...

  4. uva 10817 - Headmaster's Headache ( 状态压缩dp)

    本文出自   http://blog.csdn.net/shuangde800 题目链接: 点击打开链接 题目大意 某校有n个教师和m个求职者,已知每人的工资和能教的课程集合,要求支付最少的工资使得每 ...

  5. UVa 10817 - Headmaster's Headache(状压DP)

    链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  6. UVa 10817 Headmaster's Headache (状压DP+记忆化搜索)

    题意:一共有s(s ≤ 8)门课程,有m个在职教师,n个求职教师.每个教师有各自的工资要求,还有他能教授的课程,可以是一门或者多门. 要求在职教师不能辞退,问如何录用应聘者,才能使得每门课只少有两个老 ...

  7. UVA - 10817 Headmaster's Headache (状压类背包dp+三进制编码)

    题目链接 题目大意:有S门课程,N名在职教师和M名求职者,每名在职教师或求职者都有自己能教的课程集合以及工资,要求花费尽量少的钱选择一些人,使得每门课程都有至少两人教.在职教师必须选. 可以把“每个课 ...

  8. UVA - 10817 Headmaster's Headache (状压dp+记忆化搜索)

    题意:有M个已聘教师,N个候选老师,S个科目,已知每个老师的雇佣费和可教科目,已聘老师必须雇佣,要求每个科目至少两个老师教的情况下,最少的雇佣费用. 分析: 1.为让雇佣费尽可能少,雇佣的老师应教他所 ...

  9. HDU 4336 Card Collector (期望DP+状态压缩 或者 状态压缩+容斥)

    题意:有N(1<=N<=20)张卡片,每包中含有这些卡片的概率,每包至多一张卡片,可能没有卡片.求需要买多少包才能拿到所以的N张卡片,求次数的期望. 析:期望DP,是很容易看出来的,然后由 ...

随机推荐

  1. 荷兰国旗问题 划分成3部分 leecode

    public class Solution { public void sortColors(int[] A) { int len=A.length; int beg=0; int end=len-1 ...

  2. bzoj 1036 [ZJOI2008]树的统计Count(树链剖分,线段树)

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 10677  Solved: 4313[Submit ...

  3. Project Euler 9

    题意:三个正整数a + b + c = 1000,a*a + b*b = c*c.求a*b*c. 解法:可以暴力枚举,但是也有数学方法. 首先,a,b,c中肯定有至少一个为偶数,否则和不可能为以上两个 ...

  4. 【转】tmux入门指南

    按照官方说明,tmux是一个终端复用软件.我接触tmux也就是这几天的事情,但已经发现其强大.作为一个文艺程序员,有必要向大家分享一下,这么好的东东怎敢藏着掖着. 先用起来再说 假设你已经装好tmux ...

  5. 1109 html5 xhtml;

    XHTML 是 XML 风格的 HTML 4.01. HTML5 是下一代 HTML,取代 HTML 4.01. XHTML是基于XML发布的HTML规范,旨在规范HTML的格式. 两者提出的目的是不 ...

  6. 2013腾讯编程马拉松初赛第二场(3月22日) 小Q系列故事——为什么时光不能倒流 ---好水!!

    我以为我会是最坚强的那一个 我还是高估了自己 我以为你会是最无情的那一个 还是我贬低了自己 就算不能够在一起 我还是为你担心 就算你可能听不清 也代表我的心意 那北极星的眼泪 闪过你曾经的眼角迷离 那 ...

  7. Intellij IDEA调试

    这段时间一直在使用Intellij IDEA, 今天把调试区工具的使用方法记录于此. 先编译好要调试的程序. 1.设置断点 选定要设置断点的代码行,在行号的区域后面单击鼠标左键即可. 2.开启调试会话 ...

  8. Js- 在一个JS文件中引用另一个JS文件

    在调用文件的顶部加入下例代码: document.write(”<script language=javascript src=’/js/import.js’></script> ...

  9. struts2 表单处理

    在这篇教程里我们将探究如何处理表单提交.本文例子介绍: javabean存储表单数据 在action中重写validate方法进行简单的校验 创建一个struts2表单并和javabean匹配 jav ...

  10. Freemarker的常用技巧总结

    Freemarker的常用技巧总结 Freemarker视频教程 1,截取字符串 有的时候我们在页面中不需要显示那么长的字符串,比如新闻标题,这样用下面的例子就可以自定义显示的长度 < lt. ...