All submissions for this problem are available.
Read problems statements in Mandarin Chinese and Russian.
Mike is fond of collecting stamps. He has a lot of rare and unusual ones in his collection. Unfortunately, a few days ago he was fired from his well-paid job.
But he doesn't complain about that, he acts! That's why Mike picked up N stamps from his collection and is going to sell them. He has already placed an announcement on the Internet and got M offers. Each offer can be described as a set of stamps, that the buyer wants to buy. Now Mike needs your help to choose a set of offers, that he should accept.
He can't accept offers partially. Also, as far as Mike has the only copy of each stamp, he can sell one stamp to at most one buyer.
Of course, Mike wants to maximize the number of accepted offers. Help him!
Input
The first line contains two integer N and M, denoting the number of the stamps and the number of the offers.
The next M lines contain the descriptions of the offers. The (i+1)'th line of the input contains the description of the i'th offer and corresponds to the following pattern: Ki Ai, 1 Ai, 2, ..., Ai, Ki. Ki - is the number of the stamps, which the i'th buyer wants to buy, Ai - is the list of the stamps sorted in the ascending order.
Output
Output should contain the only integer, denoting the maximal number of the offers, that Mike can accept.
Constraints
1 ≤ N ≤ 20,000
1 ≤ M ≤ 20
1 ≤ Ki
Example
Input: 4 3 2 1 2 2 2 3 2 3 4 Output: 2
Explanation
In the example test Mike should accept the first and the third offer.
今天重做了一下codechef以前的错题。。结果发现自己真的不在状态。。
题意:有n张邮票卖。但是顾客可能一次要几张。。
问你最多可以卖给多少个顾客。每种邮票只有一张。
题解:首先看到顾客最多只有20个。所以就算是枚举也只是2^20 100w
不会超时。而且首先是计算出每两个顾客是否冲突。
然后就递归枚举。。加少量的剪枝。。
但是递归更新最大值时wa了很多次。后来才发现有一种情况没更新。。。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
int stamp[22][20002];
int xy[22][22];
int num[22],n,m,ans,f[22];
int max(int a,int b) {
return a>b?a:b;
}
int ok(int k,int p) {
int i,j = 0;
for(i=0;i<num[k] && j<num[p];) {
if(stamp[k][i]==stamp[p][j]) return 0;
else if(stamp[k][i]>stamp[p][j]) j++;
else i++;
}
return 1;
}
void make() {
int i,j;
for(i=0;i<m-1;i++)
for(j=i+1;j<m;j++)
xy[i][j] = xy[j][i] = ok(i,j);
}
bool work(int p,int a[],int len) {
int i;
for(i=0;i<len;i++) {
if(xy[a[i]][p]==0)
return 0;
}
return 1;
}
void DFS(int p,int len,int a[]) {
int i;
if(p>=m) {
ans = max(ans,len);
return ;
}
for(i=p;i<m;i++) {
if(f[i]==0 && work(i,a,len)) {
f[i] = 1;
a[len] = i;
DFS(i+1,len+1,a);
f[i] = 0;
}
}
ans = max(ans,len); //递归是忘记了最后一个不可以选择时就进不了return这个语句。然后就更新不了最大值
} //为什么要犯这种错误。。。。
int main()
{
int i,j,p;
int a[22];
scanf("%d%d",&n,&m);
for(i=0;i<m;i++) {
scanf("%d",&num[i]);
for(j=0;j<num[i];j++)
scanf("%d",&stamp[i][j]);
}
make();
ans = 1;
DFS(0,0,a);
printf("%d\n",ans);
return 0;
}
本文介绍了一个邮票销售问题的解决方法,旨在帮助一位收藏家最大化其邮票销售收益。面对有限数量的邮票和多个买家的不同需求,文章提供了一种通过递归枚举并适当剪枝的方法来确定最优的邮票销售方案。
1291

被折叠的 条评论
为什么被折叠?



