蓝桥杯-javaA组-糖果-状态压缩动态规划

时间限制: 1.0s 内存限制: 512.0MB 本题总分:25 分

【问题描述】

糖果店的老板一共有 M 种口味的糖果出售。为了方便描述,我们将 M 种 口味编号 1 ∼ M。

小明希望能品尝到所有口味的糖果。遗憾的是老板并不单独出售糖果,而 是 K 颗一包整包出售。

幸好糖果包装上注明了其中 K 颗糖果的口味,所以小明可以在买之前就知 道每包内的糖果口味。

给定 N 包糖果,请你计算小明最少买几包,就可以品尝到所有口味的糖 果。

【输入格式】

第一行包含三个整数 N、M 和 K。接下来 N 行每行 K 这整数 T1, T2, · · · , T**K,代表一包糖果的口味。

【输出格式】

一个整数表示答案。如果小明无法品尝所有口味,输出 −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≤T**i ≤M。


思路:(没学过状态压缩的小伙伴可以离开了qwq)

        这道题很明显是用状态压缩动态规划(蒟蒻刚开始做的时候居然想用并查集,后面才发现自己的算法内功还不够)。我们将每一行的糖果的状态存储下来,比如第一组数据1 1 2,我们记录成00011(假如只有五个二进制数),第二组数据1 2 3记录成00111。然后就是常规的动态规划思想了。下面直接上代码(带详细注释):

import java.io.*;
import java.util.*;

public class Main {
    public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();//n包糖果
        int m=sc.nextInt();//一共有m种口味
        int k=sc.nextInt();//一包糖果中有K颗糖果
        int[] w = new int[n+1];//用w记录每一包糖果包含的所有口味
        int[] dp = new int[1<<20];//状态压缩dp
        for(int i=1;i<=n;i++){
            for(int j=1;j<=k;j++){
                int temp=sc.nextInt();
                w[i]|=(1<<temp-1);
            }//例如,第二包糖果1 2 3,那么001|010|100 = 011|100 = 111
        }
        Arrays.fill(dp,21);//因为m<=20,求得是min,所以我们把初始值设为21
        for(int i=1;i<=n;i++){
            dp[w[i]]=1;//这里我们将每一行的情况设为1,即最少情况为买一包
            for(int j=0;j<(1<<m);j++){
                int z=j|w[i];//比如01100|00001=01101,两种情况相加
                dp[z]=Math.min(dp[z],dp[j]+1);//经典线性?
            }
        }
        //这里注意,如果(1<<m)-1的情况最少需要买21包,那说明买完20包,也买不到所有口味,输出-1
        System.out.println(dp[(1<<m)-1]<=20?dp[(1<<m)-1]:-1);
    }
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

玛卡左家陇分卡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值