UVA10817 校长的烦恼 Headmaster's Headache
UVA10817 校长的烦恼 Headmaster's Headache
题意:
一开始有一些老师,又来了一些申请者
每个老师能教一个或多个科目 校长想要选择一些申请者以保证每个科目都至少有两名老师能教 同时总共花的钱要最小。
分析:
一眼状压 \(dp\) .
我们考虑压缩科目,设置 \(dp[i][s0][s1][s2]\) ,分别表示:枚举第 \(i\) 个人,没有人教的课,有一个人教,有俩人教。
此时,我们思考一下,如果当前人能教的课程状态为 \(st[i]\) ,那么我们应该怎么转移下一次 \(dp\) 的状态:
一开始 \(s0=1111..1\) ,表示不会的课程
给出代码:
int m0=s0&st[i]; // (别人都不会&i会的)= i目前会的
int m1=s1&st[i]; // (有一个人会+i会)= 俩人都会的
s0=s0^m0;/// 在没人会的集合里面去除i会的
s1=(s1^m1)|m0;//现在有不会的
//先异或找到俩人同时会的,然后再 | m0表示至少有一个人会的
s2=s2|m1;//至少有两人的情况
//(因为它|的是已经有俩人会的情况,所以1表示就是有俩人会)
那么就很好写了,给出代码:
// UVA10817 校长的烦恼
#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
string str;
int s,n,m,val[155],st[155];
int dp[155][1<<8][1<<8];
int dfs(int i,int s0,int s1,int s2){
if(i==n+m){
return s2 == (1 << s) - 1 ? 0 : inf;
}
int &res=dp[i][s1][s2];
if(res>=0) return res;
res=inf;
if(i>=m) res=dfs(i+1,s0,s1,s2);
int m0=st[i]&s0;///别人都不会 + i会
int m1=st[i]&s1;///只有一个人会 + i会
s0=s0^m0;///在没人会的集合里面去除i会的
s1=(s1^m1)|m0;//现在有不会的
s2=s2|m1;//至少有两人的情况(因为它|的是已经有俩人会的情况,所以1表示就是有俩人会)
res=min(res,dfs(i+1,s0,s1,s2)+val[i]);
return res;
}
int main(){
while(getline(cin,str)){
stringstream ss;
ss<<str; ss>>s>>m>>n; if(!s) break;
for(int i=0;i<=m+n-1;i++){
getline(cin,str);
stringstream ss;
ss<<str;
ss>>val[i];///工资
st[i]=0;
int x;
while(ss>>x){ //每个人教的课的状态
x--;
st[i]|=(1<<x);
}
}
memset(dp,-1,sizeof dp);
printf("%d\n",dfs(0,(1<<s)-1,0,0));
}
return 0;
}
不关注的有难了😠😠😠https://b23.tv/hoXKV9