每门课至少有两名教师可以教。
定义三维d[i][s1][s2]的状态,对于第i到最后一个教师,有且只有1个老师的课的集合是s1,大于等于2个教师的课的集合是s2。
前m个教师都不能辞退,因此必须选,此时d[i][s1][s2]=d[i+1][s1'][s2'],其中s1',s2'分别是是选了第i个教师后的s1和s2。
其他教师可选可不选。
不选的话d[i][s1][s2]=d[i+1][s1][s2],即s1,s2不变。
选的话同上。
两者取最小即可。
用记忆化搜索实现。
代码
#include<bits/stdc++.h>
#define maxn 150
#define INF 0X3F3F3F3F
using namespace std;
int S,M,N;
int st[maxn];
int c[maxn];
char str[100];
int d[maxn][1<<8][1<<8];
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;
int m1=st[i]&s1;
s0^=m0;
s1^=m1;
s1|=m0;
s2|=m1;
ans=min(ans,dp(i+1,s0,s1,s2)+c[i]);
return ans;
}
int main()
{
while(scanf("%d %d %d",&S,&M,&N),S||M||N)
{
getchar();
memset(d,-1,sizeof(d));
memset(st,0,sizeof(st));
string s;
for(int i=0;i<M+N;i++)
{
cin.getline(str,100);
s=str;
stringstream ss(s);
int temp;
ss>>c[i];
while(ss>>temp) st[i]|=1<<(temp-1);
}
printf("%d\n",dp(0,(1<<S)-1,0,0));
}
return 0;
}