uva 10817 Headmaster's Headache

原题:
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

中文:
给你三个数s,m,n
分别表示有多少门课,有多少个在职教师,有多少个应聘教师
然后给你n+m行,每行有每个老师的工资和能教的课

现在要求每门课至少有两个老师教,每个老师可以教多门课,在职教师不能辞退,问你在满足每门课最少两个老师的情况下,需要花多少钱来雇佣老师

#include<bits/stdc++.h>
using namespace std;
const int maxn=1<<8;
int dp[150][maxn][maxn];
int n,m,s,st[150],c[150];
const int inf=121*50000;
int dfs(int i,int s0,int s1,int s2)
{
    if(i==m+n)
    {
        return s2==(1<<s)-1 ? 0 : inf;
    }
    int& ans=dp[i][s1][s2];
    if(ans>=0)
        return ans;
    ans=inf;
    if(i>=m)
        ans=dfs(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]+dfs(i+1,s0,s1,s2));
    return ans;
}

int main()
{
    ios::sync_with_stdio(false);
    string line;
    while(cin>>s>>m>>n)
    {
        cin.ignore();
        if(s==0)
            return 0;
        memset(dp,-1,sizeof(dp));
        memset(st,0,sizeof(st));
        for(int i=0;i<n+m;i++)
        {
            string tmp;
            int res;
            getline(cin,tmp);
            stringstream ss(tmp);
            ss>>c[i];
            while(ss>>res)
            {
                st[i]|=(1<<(res-1));
            }
            //cout<<st[i]<<endl;
        }

        int ans=dfs(0,(1<<s)-1,0,0);
        cout<<ans<<endl;
    }
    return 0;
}

解答:

紫书上面的例题,而且还附有代码~

首先从数据上来看,就能看出此题需要用状态压缩的方法来解决。
在不考虑每门课至少有两个老师教且没有在职教师的情况下,状态转移方程是这样
dp[s]=min(dp[s-{Appi}]+money[i])
其中s用状态压缩的方法来表示每门课是否有人教,{Appi}表示应聘者i能教授的课程

但是,如果考虑题目中的要求,很容易想到要保存每门课的状态S,而且这个S最好还能看出来每门课有多少人教授。如此下来,可以想到设置状态dp[S][i]表示每门课在状态S的情况下,选取到前i个应聘者最少花费的钱数。
但是,关键在于这个课的状态S如何才能表示每个课有多少人教?

考虑极限数据情况,有100个应聘者,算上在职教师有120个,假设每个老师都能教最多的8个课程,那么有2^(120×8)个状态。 明显不可能

在紫书当中,处理的很巧妙,使用两个状态,s1和s2,分别为只有一个人教课的状态和大于等于两个人教课的状态,如此下来,不需要考虑多余两个人教课的科目有多少人~ 这样就实现了状态的定义

状态压缩的转移方程还是很好想的,看代码就能明白了

创建校长信息表`HeadMaster`的SQL语句如下: ``` CREATE TABLE HeadMaster ( HeadID CHAR(4) NOT NULL, Head_Name CHAR(10) NOT NULL, S_ID CHAR(4) NOT NULL, App_Date DATETIME, CONSTRAINT PK_HeadMaster PRIMARY KEY (HeadID), CONSTRAINT FK_HeadMaster_S_ID FOREIGN KEY (S_ID) REFERENCES School(S_ID) ); ``` 其中,`HeadID`、`Head_Name`、`S_ID`、`App_Date`分别是校长信息表`HeadMaster`的列名,对应的中文列名分别是校长编号、姓名、学校编号、任职日期。数据类型和长度分别如题所述。`App_Date`列为校长的任职日期,使用了`Datetime`类型。 主键约束使用`PK_HeadMaster`名称进行命名,外键约束使用`FK_HeadMaster_S_ID`进行命名,对应`S_ID`列的外键关系。约束必须引用`School`表的`S_ID`列。 以上SQL语句创建了一个校长信息表`HeadMaster`,其中主键为`HeadID`列,`S_ID`列为`School`表的外键。 创建学校信息表`School`的SQL语句如下: ``` CREATE TABLE School ( S_ID CHAR(4) NOT NULL, S_Name VARCHAR(20) NOT NULL, s_add CHAR(20), CONSTRAINT PK_School PRIMARY KEY (S_ID) ); ``` 其中,`S_ID`、`S_Name`、`s_add`分别是学校信息表`School`的列名,对应的中文列名分别是学校编号、学校名称、学校地址。数据类型和长度分别如题所述。 主键约束使用`PK_School`名称进行命名。 以上SQL语句创建了一个学校信息表`School`,其中主键为`S_ID`列。 创建教师类型表`TeacherType`的SQL语句如下: ``` CREATE TABLE TeacherType ( TypeID CHAR(4) NOT NULL, TypeName CHAR(20) NOT NULL, CONSTRAINT PK_TeacherType PRIMARY KEY (TypeID) ); ``` 其中,`TypeID`、`TypeName`分别是教师类型表`TeacherType`的列名,对应的中文列名分别是类型编号、类型名称。数据类型和长度分别如题所述。 主键约束使用`PK_TeacherType`名称进行命名。 以上SQL语句创建了一个教师类型表`TeacherType`,其中主键为`TypeID`列。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值