这个题可被数组坑死了。 自己给自己挖坑啊
数组开到200 明显过不了。。 只有至少256.。 交了n遍。。 坑啊。。 详细描述 看代码注释。
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <string>
#include <map>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <cctype>
using namespace std;
#define ll long long
#define maxn 150+10
#define INF 1<<30
int st[maxn]; // 第i个人能教的科目集合
int c[maxn]; // 第i个人的工资
int d[maxn][300][300];
int s,m,n;
int dp(int i, int s0, int s1, int s2){ // 第i个人 没有教过的集合s0 一个人教过的s1 两个人教过的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) // 大于了m 之后 为 求职者 可以不选
ans = dp(i+1, s0, s1, s2);
int m0 = st[i] & s0, m1 = st[i] & s1; //把第i个人可以教的科目与没教过的求交集 和 一个人教过的求交集
s0 ^= m0; s1 = (s1 ^ m1) | m0;// 从 s0 中的集合 去除m0 这个元素 并且加入s1中去
s2 |= m1; // 同时把s1 去除m1 把m1 加到 s2 中去
ans = min(ans, c[i]+dp(i+1, s0, s1, s2));
return ans;
}
int main (){
while(scanf("%d%d%d",&s,&m,&n) !=EOF && s){
getchar();
memset(st,0,sizeof(st));
memset(c,0,sizeof(c));
memset(d,-1,sizeof(d));
char ch[maxn];
for(int i = 0; i < m; i++){
gets(ch);
sscanf(ch,"%d",&c[i]);
int len = strlen(ch);
for(int j = 6; j < len; j++){
if(isdigit(ch[j])){
int x;
sscanf(ch+j,"%d", &x);
st[i] = st[i] | (1 << (x-1));
}
while(j < len && isdigit(ch[j]))
j++;
}
}
for(int i = m; i < n+m; i++){
gets(ch);
sscanf(ch,"%d",&c[i]);
int len = strlen(ch);
for(int j = 6; j < len; j++){
if(isdigit(ch[j])){
int x;
sscanf(ch+j,"%d", &x);
st[i] |= (1 << (x-1));
}
while(j < len && isdigit(ch[j]))
j++;
}
}
int ans = dp(0,(1 << s) - 1, 0, 0);
printf("%d\n",ans);
}
return 0;
}