题意:
披萨只有9种部位
有n个人,他们每个人需要一些部位,如果他所需要的部位都有,呢么他就满足
有m个披萨,每种披萨有若干部位,每种披萨有一定的价钱
只能购买2个披萨,在满足最多人满足的情况下,选择花费最小的两个披萨
解析:
贪心+二进制优化,处理的细节较多
一共9个部位,可以用二进制压缩,披萨最多512种
输出的结果可能是两个不同类型的披萨,也可能是两个相同类型的披萨
所以要记录相同类型,价钱最小的两个披萨
对i==j和i!=j两种情况分别贪心
ac:
#include<bits/stdc++.h>
#define pb push_back
#define ll long long
#define MAXN 100005
#define MAX 1<<10
using namespace std;
/*
贪心,二进制优化
*/
struct node
{
int c,id;
friend bool operator <(node a,node b)
{
return a.c<b.c;
}
};
vector<node> vg[MAX];
int val[MAXN];
int num[MAX];
int mk[MAX][2];
int id[MAX][2];
int main()
{
int n,m,x,t;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)//人
{
scanf("%d",&t);
int c=0;
while(t--)
{
scanf("%d",&x);
c|=(1<<(x-1));
}
num[c]++;
}
for(int i=1;i<=m;i++)
{
scanf("%d%d",&val[i],&t);
int c=0;
while(t--)
{
scanf("%d",&x);
c|=(1<<(x-1));
}
vg[c].pb({val[i],i});
}
for(int i=0;i<512;i++)
{
if(vg[i].size()==0)
continue;
sort(vg[i].begin(),vg[i].end());
mk[i][0]=vg[i][0].c;
id[i][0]=vg[i][0].id;
if(vg[i].size()>1)
{
mk[i][1]=vg[i][1].c;
id[i][1]=vg[i][1].id;
} //记录价钱最小的两种
}
int ans=-1,ans1=0,ans2=0,maxs=1e9,sum;
for(int i=0;i<512;i++)
{
for(int j=i;j<512;j++)
{
sum=0;
if(i==j&&vg[i].size()>1)//买两个同类型披萨
{
for(int k=0;k<512;k++)
{
int v=i&k;
if(v==k)//i包含k
sum+=num[k];
}
if(sum>ans)//满足的人多
{
ans=sum;
ans1=i;
ans2=j;
maxs=mk[i][0]+mk[j][1];
}
if(sum==ans&&maxs>mk[i][0]+mk[j][1])//满足的人同样多,价钱更便宜
{
ans1=i;
ans2=j;
maxs=mk[i][0]+mk[j][1];
}
}
if(i!=j&&vg[i].size()>0&&vg[j].size()>0)//买两个不同类型披萨
{
for(int k=0;k<512;k++)
{
int v=(i|j)&k;
if(v==k)//(i+j)包含k
sum+=num[k];
}
if(sum>ans)
{
ans=sum;
ans1=i;
ans2=j;
maxs=mk[i][0]+mk[j][0];
}
if(sum==ans&&maxs>mk[i][0]+mk[j][0])
{
ans1=i;
ans2=j;
maxs=mk[i][0]+mk[j][0];
}
}
}
}
if(ans1==ans2)
printf("%d %d\n",id[ans1][0],id[ans2][1]);
else
printf("%d %d\n",id[ans1][0],id[ans2][0]);
return 0;
}