蓝桥杯2019-省赛-C/C++-A组I题
状态压缩dp
题目
糖果
【问题描述】
糖果店的老板一共有 M 种口味的糖果出售。为了方便描述,我们将 M 种 口味编号 1 ∼ M。
小明希望能品尝到所有口味的糖果。遗憾的是老板并不单独出售糖果,而 是 K 颗一包整包出售。
幸好糖果包装上注明了其中 K 颗糖果的口味,所以小明可以在买之前就知 道每包内的糖果口味。
给定 N 包糖果,请你计算小明最少买几包,就可以品尝到所有口味的糖 果。
【输入格式】
第一行包含三个整数 N、M 和 K。
接下来 N 行每行 K 这整数 T1, T2, · · · , TK ,代表一包糖果的口味。
【输出格式】
一个整数表示答案。如果小明无法品尝所有口味,输出 −1。
【样例输入】
6 5 3
1 1 2
1 2 3
1 1 3
2 3 5
5 4 2
5 1 2
【样例输出】
2
【评测用例规模与约定】
对于 30% 的评测用例,1 ≤ N ≤ 20 。
对于所有评测样例,1 ≤ N ≤ 100,1 ≤ M ≤ 20,1 ≤ K ≤ 20,1 ≤ Ti ≤ M。
代码
1 #include<iostream> 2 #include<cmath> 3 #include<string.h> 4 using namespace std; 5 int main(){ 6 int n,m,k; 7 cin>>n>>m>>k; 8 int dp[1<<m+5]; 9 int goods[n]; 10 int ss,s; 11 memset(dp,-1,sizeof(dp));//dp数组初始化 12 for(int i=0;i<n;i++){ 13 ss=0; 14 for(int j=0;j<k;j++){ 15 cin>>s; 16 ss|=(1<<(s-1));//用二进制形式表示货物的状态,比如, 17 //总共有5种糖果,那么我们的二进制位数应该是5位 18 //一袋糖果有3个糖果,他们分别是1,2,3,那么对应 19 //的状态就是00111 20 } 21 goods[i]=ss; 22 dp[ss]=1; 23 } 24 for(int i=0;i<n;i++){ 25 for(int j=0;j<(1<<m);j++){ 26 if(dp[j]==-1) continue;//无该状态,返回 27 if(dp[j|goods[i]]==-1) //新组合的状态的信息未记录,记录下 28 dp[j|goods[i]]=dp[j]+dp[goods[i]]; 29 else//新组合的状态遇见更好的方案,未更新,更新下 30 dp[j|goods[i]]=min(dp[j|goods[i]],dp[j]+dp[goods[i]]); 31 } 32 } 33 cout<<dp[(1<<m)-1]<<endl;//输出要所有类型糖果的最少的产品数 34 }
我们不会停下探寻明天的脚步

浙公网安备 33010602011771号