二進制枚舉:幼兒園買玩具

問題描述


蒜廠幼兒園有n 個小朋友,每個小朋友都有自己想玩的玩具。身爲幼兒園園長的你決定給幼兒園買一批玩具,由於經費有限,你只能買m 個玩具。已知玩具商店一共賣k種玩具,編號爲1,2,3,…k,你讓每個小朋友把想玩的玩具編號都寫在了紙上。你希望滿足儘可能多的小朋友的需求,請計算出最多能滿足多少個小朋友的玩具需求。


輸入格式


第一行,輸入三個整數n,m,k(1≤n≤100,1≤m≤k≤15),中間用空格分開。
接下來n 行,第i+1行的第一個數字ai代表第i 個小朋友想玩的玩具數量,接下來有ai個數字,代表這 ai個玩具的編號。


輸出格式


輸出一個整數,表示最多能滿足多少小朋友的玩具需求。


樣例輸入


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

樣例輸出


3

思路:用二進制枚舉的方式枚舉不同的情況(也即遍歷玩具的子集),然後判斷是否合法,然後取最大的滿足人數。
ps:枚舉時應考慮超時問題,枚舉變量應儘可能小,此題n較大,則應考慮枚舉k而不是n。
代碼如下:

#include<iostream>
#include<cstring>
using namespace std;
struct a
{
    int num;
    int w[15];
}aa[100];
int main()
{
    int n,m,k;
    cin>>n>>m>>k;
    for(int i=0;i<n;i++)
    {
        cin>>aa[i].num;
        for(int j=0;j<aa[i].num;j++)
            cin>>aa[i].w[j];
    }
    int max=0;//記錄能夠滿足的小朋友數目的最大值
    for(int i=0;i<(1<<k);i++)
    {
        int bsum=0;//當前子集中包含的玩具個數
        int b[15];//用於標記在當前子集中的玩具
        memset(b,0,sizeof(b));
        for(int j=0;j<k;j++)
        {
            if(i&(1<<j))//判斷該玩具是否是當前子集中的玩具
            {
                bsum++;//玩具個數+1
                b[j]=1;//打上標記
            }
            int sum=0;//記錄能夠滿足的小朋友的數目
            for(int x=0;x<n;x++)
            {
                int flag=1;//判斷當前小朋友的要求是否被滿足
                for(int y=0;y<aa[x].num;y++)//遍歷小朋友要求的玩具
                    if(b[aa[x].w[y]-1]==0)
                        flag=0;
                if(flag==1)
                    sum++;
            }
            if(sum>max&&bsum<=m)
                max=sum;                        
        }
    }
    cout<<max<<endl;
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章