VOJ 幼儿园买玩具 题解 二进制枚举

幼儿园买玩具

题目描述

幼儿园有 n n n 个小朋友,每个小朋友都有自己想玩的玩具。身为幼儿园园长的你决定给幼儿园买一批玩具,由于经费有限,你只能买 m m m 个玩具。已知玩具商店一共卖 k k k 种玩具,编号为 1 , 2 , 3 , … k 1,2,3,…k 1,2,3,k, 你让每个小朋友把想玩的玩具编号都写在了纸上。你希望满足尽可能多的小朋友的需求,请计算出最多能满足多少个小朋友的玩具需求。

输入描述

第一行,输入三个整数 n , m , k ( 1 ≤ n ≤ 100 , 1 ≤ m ≤ 15 , 1 ≤ k ≤ 15 ) n,m,k(1≤n≤100,1≤m≤15,1≤k≤15) n,m,k(1n100,1m15,1k15),中间用空格分开。接下来 n n n 行,第 i + 1 ( 0 ≤ i < n ) i+1(0≤i<n) i+1(0i<n) 行的第一个数字 a i a_i ai 代表第 i i i 个小朋友想玩的玩具数量,接下来有 a i a_i ai 个数字,代表这 a i a_i ai 个玩具的编号。

输出描述

输出一个整数,表示最多能满足多少小朋友的玩具需求。

用例输入 1

5 3 5
2 1 4
0
2 3 1 
3 2 3 4 
2 4 5

用例输出 1

3

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int n, m, k;
    cin >> n >> m >> k;
    vector<vector<int>> v(n + 1);
    for (int i = 1; i <= n; i++)
    {
        int num; // 该小朋友想玩的玩具数量
        cin >> num;
        int temp; // 玩具编号
        for (int j = 0; j < num; j++)
        {
            cin >> temp;
            v[i].push_back(temp);
        }
    }
    if (m >= k)
    {
        cout << n;
        return 0;
    }
    int ans = 0;
    for (int i = 0; i < (1 << k); ++i) // 二进制枚举所有玩具选择情况
    {
        int is[16] = {0}; // 记录该二进制状态下选择的玩具编号
        int cnt = 0;      // 该二进制状态下选择买的玩具的数量
        for (int j = 0; j < k; j++)
        {
            if (i & (1 << j))
                is[j + 1] = 1, cnt++;
        }
        if (cnt == m) // 根据贪心,尽可能多的买玩具能满足更多小朋友的需求,所以只需考虑cnt==m的情况
        {
            int temp = 0; // 当前选择方案能满足小朋友需求的数量
            for (int k = 1; k <= n; k++)
            {
                bool ok = 1; // 判断是否满足该小朋友的需求
                int num = v[k].size();
                for (int s = 0; s < num; s++)
                {
                    if (is[v[k][s]] == 0)
                    {
                        ok = 0;
                        break;
                    }
                }
                if (ok)
                    temp++;
            }
            ans = max(temp, ans); // 维护ans为最大值
        }
    }
    cout << ans;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值