糖果店的老板一共有 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。
6 5 3
1 1 2
1 2 3
1 1 3
2 3 5
5 4 2
5 1 2
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 题。
你一看这个题,数据那么少,N<=20就,而且这个要求是买所有的糖果所以只要知道这种糖果有没有就可以了就是0/1。那这样为了节省空间就可以用二进制0/1来表示这个糖果是不是买了/ 所以这就是一个状态压缩dp。
int n, m, k, x;
int a[400];
int dp[1 << 21];
int main()
{
cin >> n >> m >> k;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= k; j++)
{
// 读入每包糖果
cin >> x;
a[i] |= 1 << (x - 1);
}
}
memset(dp, 0x3f, sizeof(dp)); // 初始化dp为最大值
dp[0] = 0; // 最小访问次数
for (int i = 1; i <= n; i++)//访问每包糖果
{
for (int j = 0; j < (1 << m); j++)//访问每个状态
{
}
}
if (dp[j] > n){
continue;
}
// 将原来得到糖果所需的次数与当前次数+1(要这袋糖果)比较并赋值
dp[j | a[i]] = min(dp[j | a[i]], dp[j] + 1);
// (1<
if (dp[(1 << m) - 1] > n){
cout << -1;
}//>n就买不到了
else{
cout << dp[(1 << m) - 1];
}//直接输出次数
#include
using namespace std;
int n, m, k, x;
int a[400];
int dp[1 << 21];
int main()
{
cin >> n >> m >> k;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= k; j++)
{
// 读入每包糖果
cin >> x;
a[i] |= 1 << (x - 1);
}
}
memset(dp, 0x3f, sizeof(dp)); // 初始化dp为最大值
dp[0] = 0; // 最小访问次数
for (int i = 1; i <= n; i++)//访问每包糖果
{
for (int j = 0; j < (1 << m); j++)//访问每个状态
{
// 如果最小次数已经大于n(买不到喽)
if (dp[j] > n){
continue;
}
// 将原来得到糖果所需的次数与当前次数+1(要这袋糖果)比较并赋值
dp[j | a[i]] = min(dp[j | a[i]], dp[j] + 1);
}
}
// (1<
if (dp[(1 << m) - 1] > n){
cout << -1;
}//>n就买不到了
else{
cout << dp[(1 << m) - 1];
}//直接输出次数
return 0;
}
本人从洛谷做的,要是别的oj通不过直接评论区留言~~~,洛谷有一些时候写错了直接给我ac了。
侵权联系删除。