# 糖果 糖果店的老板一共有M种口味的糖果出售。为了方便描述,我们将M种口味编号1~M。 小明希望能品尝到所有口味的糖果。遗憾的是老板并不单独出售糖果,而是K颗一包整包出售。 幸好糖果包装上注明了其中K颗糖果的口味,所以小明可以在买之前就知道每包内的糖果口味。 给定包糖果,请你计算小明最少买几包,就可以品尝到所有口味的糖果。 **输入** 第一行包含三个整数N、M 和K。 接下来N 行每行K 这整数$T_1,T_2,…,T_K$,代表一包糖果的口味。 1<=N<=100,1<=M<=20,1<=K<=20,1<=$T_i$<=M。 **输出** 一个整数表示答案。如果小明无法品尝所有口味,输出-1。 **样例输入** ``` 6 5 3 1 1 2 1 2 3 1 1 3 2 3 5 5 4 2 5 1 2 ``` **样例输出** ``` 2 ``` 以下错误的一项是? ## aop ### before ```cpp #include using namespace std; ``` ### after ```cpp ``` ## 答案 ```cpp const int N = 105, M = (1 << 20) + 10; int n, m, k, x, a[N], dp[M]; int main() { ios::sync_with_stdio(false); cin >> n >> m >> k; memset(dp, -1, sizeof(dp)); for (int i = 1; i <= n; i++) { int s = 0; for (int j = 1; j <= k; j++) { cin >> x; s |= (1 << (x - 1)); } dp[s] = 1; a[i] = s; } for (int i = 1; i <= n; i++) { for (int j = 0; j < (1 << m); j++) { if (dp[j] == -1) continue; int to = j | a[i]; if (dp[to] != -1) { dp[to] = min(dp[to], dp[j]); } else { dp[to] = dp[j] + 1; } } } printf("%d\n", dp[(1 << m) - 1]); return 0; } ``` ## 选项 ### A ```cpp int n, m, k; int dp[1 << 20]; vector a; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); cin >> n >> m >> k; for (int i = 0; i < (1 << m); i++) { dp[i] = 9999; } for (int i = 0; i < n; i++) { int s = 0; for (int i = 0; i < k; i++) { int temp; cin >> temp; s |= 1 << (temp - 1); } a.push_back(s); } dp[0] = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < (1 << m); j++) { if (dp[j] == 9999 || (j | a[i]) == j) continue; dp[j | a[i]] = min(dp[j] + 1, dp[j | a[i]]); } } if (dp[(1 << m) - 1] == 9999) cout << -1; else cout << dp[(1 << m) - 1]; return 0; } ``` ### B ```cpp const int maxn = (1 << 20) + 52; const int inf = 9; int a[505], n, m, k, dp[2][maxn]; int min(int a, int b, int c) { return min(min(a, b), c); } int main() { scanf("%d%d%d", &n, &m, &k); int e = 1 << m; for (int i = 1; i <= n; i++) { a[i] = 0; for (int j = 0; j < k; j++) { int temp; scanf("%d", &temp); a[i] = a[i] | 1 << (temp - 1); } } for (int i = 0; i < maxn; i++) { dp[0][i] = dp[1][i] = inf; } dp[0][0] = 0; bool pos = 1; for (int i = 1; i <= n; i++, pos = !pos) { for (int j = 0; j < e; j++) { dp[pos][j] = dp[!pos][j]; } for (int j = 0; j < e; j++) { dp[pos][j | a[i]] = min(dp[pos][j | a[i]], dp[!pos][j | a[i]], dp[!pos][j] + 1); } } if (dp[!pos][e - 1] == inf) { printf("-1\n"); } else printf("%d\n", dp[!pos][e - 1]); return 0; } ``` ### C ```cpp int dp[1 << 20]; int ST[100]; int main() { int n, m, k; cin >> n >> m >> k; int tot = (1 << m) - 1; memset(dp, -1, sizeof dp); for (int i = 0; i < n; i++) { int st = 0; for (int j = 0; j < k; j++) { int x; cin >> x; st |= (1 << x - 1); } dp[st] = 1; ST[i] = st; } for (int i = 0; i <= tot; i++) { if (dp[i] != -1) { for (int j = 0; j < n; j++) { int st = ST[j]; if (dp[i | st] == -1 || dp[i | st] > dp[i] + 1) dp[i | st] = dp[i] + 1; } } } cout << dp[tot]; return 0; } ```