[蓝桥杯 2019 省 A] 糖果
题目描述
糖果店的老板一共有 M M M 种口味的糖果出售。为了方便描述,我们将 M M M 种口味编号 1 1 1 ∼ M M M。
小明希望能品尝到所有口味的糖果。遗憾的是老板并不单独出售糖果,而是 K K K 颗一包整包出售。
幸好糖果包装上注明了其中 K K K 颗糖果的口味,所以小明可以在买之前就知道每包内的糖果口味。
给定 N N N 包糖果,请你计算小明最少买几包,就可以品尝到所有口味的糖果。
输入格式
第一行包含三个整数 N N N、 M M M 和 K K K。
接下来 N N N 行每行 K K K 这整数 T 1 , T 2 , ⋯ , T K T_1,T_2, \cdots ,T_K T1,T2,⋯,TK,代表一包糖果的口味。
输出格式
一个整数表示答案。如果小明无法品尝所有口味,输出 − 1 -1 −1。
样例 #1
样例输入 #1
6 5 3
1 1 2
1 2 3
1 1 3
2 3 5
5 4 2
5 1 2
样例输出 #1
2
提示
对于 30 % 30\% 30% 的评测用例, 1 ≤ N ≤ 20 1 \le N \le 20 1≤N≤20。
对于所有评测样例, 1 ≤ N ≤ 100 1 \le N \le 100 1≤N≤100, 1 ≤ M ≤ 20 1 \le M \le 20 1≤M≤20, 1 ≤ K ≤ 20 1 \le K \le 20 1≤K≤20, 1 ≤ T i ≤ M 1 \le T_i \le M 1≤Ti≤M。
蓝桥杯 2019 年省赛 A 组 I 题。
思路
因为本道题的 1 ≤ N ≤ 100 1 \le N \le 100 1≤N≤100,所以我们可以考虑使用二进制压缩的方式来做题
代码
#include<iostream>
#include<cstring>
#define int long long
using namespace std;
const int N = 110,M = 1<<20;
int n,m,k;
int f[M],w[N];
signed main(){
cin>>n>>m>>k;
int ed=(1<<m)-1;
int x;
for(int i=1;i<=n;i++){
int state=0;
for(int j=1;j<=k;j++){
cin>>x;
state|=(1<<(x-1));
}
w[i]=state;
}
memset(f,0x3f,sizeof f);
f[0]=0;
for(int i=1;i<=n;i++){
for(int j=ed;j>=0;j--){
f[j]=min(f[j],f[j&(~w[i])]+1);
}
}
if(f[ed]>=2e9)f[ed]=-1;
cout<<f[ed];
return 0;
}