NKOJ 3700 校长的烦恼
时间限制 : - MS 空间限制 : 65536 KB
评测说明 : 时限1000ms
问题描述
某中学开设有s门课程,现有教师m个。今天有n个求职者来应聘新教师。
已知每个人工资和能教授的课程。
在职教师不能辞退,校长想知道,最少支付多少工资就能使得每门课都有至少两名教师能教。
输入格式
第一行,三个整数s,m和n
接下来m行,每行若干个整数,描述一名在职教师的情况:第一个整数,表示该教师的工资,接下来的若干整数表示该教师能教的课程;
接下来n行,每行若干个整数,描述一名求职者的情况:第一个整数,表示该求职者要求的工资,接下来的若干整数表示该求职者能教的课程;
注意,每行末尾有空格
输出格式
一行,一个整数,表示所求结果。
若无解,输出-1
样例输入 1
2 2 2
10000 1
20000 2
30000 1 2
40000 1 2
样例输出 1
60000
样例输入 2
5 2 4
24 2 4
39 4 1
9 4
81 2 1 5
19 2 3 5
65 3 1
样例输出 2
228
提示
1<=s<=8
1<=m<=20
1<=n<=100
1<=每个人的工资<=50000
1<=每个人教的课的编号<=s
来源 改编自uva 10817
状态:f[s2][s1]表示至少有一名教师教的课程为s1,至少两名教师教的课程为s2,时取得的最小代价
决策:每名应聘教师选或者不选
方程:f[s2][s1]=min(f[i][j]+cost[k])
#include<cstdio>
#include<iostream>
using namespace std;
const int inf=1e9;
const int need=(1<<8)+4;
int ab[103],cost[103],f[need][need];
int a,n,m;
char *p;
void get(int &c)
{
for(c=0;*p>='0'&&*p<='9';p++) c=c*10+*p-'0';
}
int main()
{
scanf("%d%d%d",&a,&m,&n);
char b[1000];
int cnt=0,temp,mn=m+n,s1=0,s2=0,c;
int s=(1<<a)-1;
gets(b);
for(int i=1;i<=mn;i++)
{
gets(b);
p=b;
get(c);
if(i<=m) cnt+=c;
else cost[i-m]=c;
while(*p==' '&&*(p+1)>='0'&&*(p+1)<='9')
{
p++;
get(c);
c--;
if(i<=m)
{
if(s1&(1<<c)) s2|=(1<<c);
else s1|=(1<<c);
}
else ab[i-m]|=1<<c;
}
}
for(int j,i=0;i<=s;i++)
for(j=0;j<=s;j++)
f[i][j]=inf;
f[s2][s1]=cnt;
for(int i,j,k=1;k<=n;k++)
for(i=s;i>=0;i--)
for(j=s;j>=0;j--)
{
if(f[i][j]>=inf) continue;
s2=i|(j&ab[k]);
s1=j|ab[k];
f[s2][s1]=min(f[s2][s1],f[i][j]+cost[k]);
}
printf("%d",f[s][s]);
}