紫书dp 用位表示集合 其中位运算集合需要注意下
#include<bits/stdc++.h>
using namespace std ;
int m,n,s;
int d[150][1<<10][1<<10];
int c[150];
int st[150];
string temp;
const int INF=1<<20;
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;//m0:该老师能教的现在没有任何人能教的课程
s0^=m0,s1=(s1^m1)|m0;//m1:该老师能教的现在有一个人能教的课程
s2|=m1;
ans=min(ans,c[i]+dp(i+1,s0,s1,s2));
return ans;
}
int main(){
while(cin>>s>>m>>n){
if(s==0)break;
int x;
getchar();
for(int i=0;i<m+n;i++){
getline(cin,temp);
stringstream ss(temp);
ss>>c[i];
st[i]=0;
while(ss>>x)st[i]|=(1<<(x-1));
}
memset(d,-1,sizeof(d));
cout<<dp(0,(1<<s)-1,0,0)<<endl;
}
return 0;
}