UVa-10817 Headmaster's Headache (位运算)

#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(10000C50000), 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题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值