糖果 | 第十届蓝桥杯省赛C++A组

糖果店的老板一共有 M 种口味的糖果出售。

为了方便描述,我们将 M 种口味编号 1∼M。

小明希望能品尝到所有口味的糖果。

遗憾的是老板并不单独出售糖果,而是 K 颗一包整包出售。

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

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

输入格式

第一行包含三个整数 N,M,K。

接下来 N 行每行 K 个整数 T1,T2,···,TK,代表一包糖果的口味。

输出格式

一个整数表示答案。

如果小明无法品尝所有口味,输出 −1。

数据范围

1≤N≤100,

1≤M,K≤20,

1≤Ti≤M

输入样例:
复制代码
6 5 3
1 1 2
1 2 3
1 1 3
2 3 5
5 4 2
5 1 2
输出样例:
复制代码
2
题解:

开始使用DFS做,每种糖果包只有选和不选两种情况,结果就TLE了。

因为只有选和不选两种状态,数据量又不是很大,很可能是使用状压DP,(但是可以直接看tag)。

首先是通过位运算,把当前每包的状态列出来。

然后制作一个2^m大小的数组dp记录全部情况达成的最小次数。

遍历这n包糖果的情况,从dp最后一位开始遍历,即m=5情况下,从11111开始遍历。

其中的 j&(~N[i]) 语句是列举出原情况包含的所有子情况,比如例题中的1 1 2,写出情况就是0 0 0 1 1(从后往前是1-k),每一位翻转后就是1 1 1 0 0,因为当前只有0 0 0 0 0是有数的,初始为0。则当遍历到情况0 0 0 1 1、0 0 0 0 1、0 0 0 1 0这三种情况时,才会按位或得到0 0 0 0 0,所以才会全部赋值为1,即当只需要1只需要2只需要1和2这三种情况最少抽1包就可以满足。

当然,这道题还可以用 dfs+剪枝+排序优化+去除优化+IDA* 做,但是不如这个简单,(实际上是懒)。

代码:
cpp 复制代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iomanip>
#include<queue>
#include<stack>
#include<vector>
#include<unordered_set>
#include<unordered_map>
#include<map>
#include<set>
using namespace std;
typedef long long int ll;

/*
6 5 3
1 1 2
1 2 3
1 1 3
2 3 5
5 4 2
5 1 2
*/
#define INF 0x3f3f3f3f

int n,m,k;
int N[101]={0};
int dp[1<<21]={0};

int main(){
    cin >> n >> m >> k;
    for(int i=1;i<=n;i++){
        for(int j=0;j<k;j++){
            int a;
            cin >> a;
            N[i]|=(1<<(a-1));
        }
    }
    memset(dp,INF,sizeof dp);
    dp[0]=0;
    for(int i=1;i<=n;i++){
        for(int j=(1<<m)-1;j>0;j--){
            dp[j]=min(dp[j],dp[j&(~N[i])]+1);
        }
    }
    if(dp[(1<<m)-1]==INF){
        cout << -1 << "\n";
    }
    else{
        cout << dp[(1<<m)-1] <<"\n";
    }
}
相关推荐
freyazzr36 分钟前
C++八股 | Day3 | 智能指针 / 内存管理 / 内存分区 / 内存对齐
开发语言·c++
蒟蒻小袁36 分钟前
力扣面试150题--课程表
算法·leetcode·面试
闻缺陷则喜何志丹39 分钟前
【动态规划】B4336 [中山市赛 2023] 永别|普及+
c++·算法·动态规划·洛谷
序属秋秋秋42 分钟前
《C++初阶之入门基础》【普通引用 + 常量引用 + 内联函数 + nullptr】
开发语言·c++·笔记
筏.k43 分钟前
C++ 网络编程(10) asio处理粘包的简易方式
java·网络·c++
belldeep1 小时前
C++:用 libcurl 发送一封带有附件的邮件
c++·curl·send·email·smpt
虾球xz1 小时前
CppCon 2015 学习:Transducers, from Clojure to C++
开发语言·c++·学习
不二狗2 小时前
每日算法 -【Swift 算法】电话号码字母组合
开发语言·算法·swift
AL流云。2 小时前
【优选算法】分治
数据结构·算法·leetcode·排序算法
派阿喵搞电子6 小时前
在UI界面内修改了对象名,在#include “ui_mainwindow.h“没更新
c++·qt·ubuntu·ui