题目大意:校长需要s门课,每门至少有两名老师来教,所以他现在想要招老师啦。当然,校长手头本来就有m个老师,每个老师都教着一个或多个课程,这些老师是不能解雇的,必须用。然后现在又n个老师来应聘,每个都有价格和他们能教的课程,校长希望花最少的钱达到他的目标,问:最少多少钱呢?

解题报告:
dp[s1][s2]
来表示第i节课,有1个老师教的集合s1,有2个老师教的集合s2,最小的花费。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
#define Inf 0x3f3f3f3f
const int N = 150;
const int maxs = 9;
int S, n, m;
int C[N], st[N];
int dp[N][1<<maxs][1<<maxs];
int d( 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>=n ) ans=d(i+1,s0,s1,s2);
int m1=st[i]&s0, m2=st[i]&s1;
s0^=m1; s1=(s1^m2)|m1; s2|=m2;
ans=min(ans, C[i]+d(i+1,s0,s1,s2) );
return ans;
}
int get(){
int x=0; char ch=getchar();
while( ch!='\n' ){
if( isdigit(ch) ) x+=1<<(ch-'1');
ch=getchar();
}
return x;
}
int main(){
while( scanf("%d%d%d", &S, &n, &m)==3 && S ){
for ( int i=0; i<n+m; i++ ){
int x, y;
scanf("%d", &C[i]);
st[i]=get();
}
memset(dp,-1,sizeof(dp));
printf("%d\n", d(0,(1<<S)-1,0,0) );
}
}