uva10817 Headmaster's Headache

The headmaster of Spring Field School is consider- ing employing
some new teachers for certain subjects. There are a number of teach-
ers applying for the posts. Each teacher is able to teach one or more
subjects. The headmaster wants to select applicants so that each sub-
ject 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 rst 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 rst 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.

状压dp,记录下来现在有两个以上人教、一个人教的集合,然后枚举当前这个人雇佣或者不雇佣。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int oo=0x3f3f3f3f;
int dp[130][1<<10][1<<10],a[130],c[130],n,m,s;
#define DP dp[p][s2][s1]
bool read(int &x)
{
    x=0;
    char c=getchar();
    while (c<'0'||c>'9') c=getchar();
    while (c>='0'&&c<='9')
    {
        x=x*10+c-'0';
        c=getchar();
    }
    return c==' ';
}
int dfs(int p,int s2,int s1,int s0)
{
    if (DP>=0) return DP;
    if (p==m+n) return s2==(1<<s)-1?0:oo;
    if (p>=m) DP=dfs(p+1,s2,s1,s0);
    else DP=oo;
    int x=s1&a[p],y=s0&a[p],ss2,ss1,ss0;
    ss2=s2+x;
    ss1=s1-x+y;
    ss0=s0-y;
    DP=min(DP,c[p]+dfs(p+1,ss2,ss1,ss0));
    return DP;
}
int main()
{
    int i,x;
    bool flag;
    while (1)
    {
        read(s);
        read(m);
        read(n);
        if (s==0) return 0;
        memset(a,0,sizeof(a));
        for (i=0;i<m+n;i++)
        {
            read(c[i]);
            while (1)
            {
                flag=read(x);
                a[i]|=1<<(x-1);
                if (!flag) break;
            }
        }
        memset(dp,0xff,sizeof(dp));
        printf("%d\n",dfs(0,0,0,(1<<s)-1));
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值