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!
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 should contain the only integer, denoting the maximal number of the offers, that Mike can accept.
1 ≤ N ≤ 20,000
1 ≤ M ≤ 20
1 ≤ Ki
Input: 4 3 2 1 2 2 2 3 2 3 4 Output: 2
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; }
codechef Mike and Stamps,布布扣,bubuko.com
原文:http://blog.csdn.net/min_lala/article/details/24045231