UVA10817 Headmaster's Headache dp+二进制集合

来源:互联网 发布:mongodb 数据库设计 编辑:程序博客网 时间:2024/06/10 16:31

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

题目大意
m教师,n求职者,共同竞聘s门课程。要求:每门课程须有两名科任老师,教师必须聘用。
解题思路
直接给出状态转移方程,具体含义详见代码。
d[i][s1][s2] = min(d[i+1][s1’][s2’]+c[i], d[i+1][s1][s2]);
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

#include"stdafx.h"#include<iostream>#include<cstring>#include<algorithm>#include<cstdio>#include<sstream>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];//c[maxn]表示聘金,st[maxn]表示可以教授的科目,d[][][]表示已考虑的最小花费//s0表示目前需要招聘两位教师的科目,s1表示需要招聘一位老师的科目,s2表示已完成招聘的科目,其中二进制中1均表示待招聘int dp(int i, int s0, int s1, int s2){    if (i == m + n) return s2 == (1 << s) - 1 ? 0 : INF;//s2的二进制位1表示还需要安排老师教学。0表示该门课不需要再安排老师教学    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;//m0,m1运算得到第i位应聘者应聘的职务是否还有空缺    s0 ^= m0;//更新s0,如果i应聘成功,则该位应置为0    s1 = (s1^m1) | m0;//s1更新,先更新被m1可行的科目,在更新从s0变成m1的科目    s2 |= m1;//更新从s1转变为s2的科目    ans = min(ans, c[i] + dp(i + 1, s0, s1, s2));//递归求解    return ans;}int main(){    int x;    string line;    while (getline(cin, line))    {        stringstream ss(line);        ss >> s >> m >> n;        if (s == 0) break;        //读入数据        for (int i = 0; i < m + n; i++)        {            getline(cin, line);            stringstream ss(line);            ss >> c[i];            st[i] = 0;            while (ss >> x)st[i] |= (1 << (x - 1));//对st初始化        }        memset(d, -1, sizeof(d));        cout << dp(0, (1 << s) - 1, 0, 0) << endl;//中间位运算,将s0全部置为1,表示都还没有添加应聘者    }    return 0;}
0 0
原创粉丝点击