问题描述
Alas! A set of D (1 <= D <= 15) diseases (numbered 1..D) is running through the farm. Farmer John would like to milk as many of his N (1 <= N <= 1,000) cows as possible. If the milked cows carry more than K (1 <= K <= D) different diseases among them, then the milk will be too contaminated and will have to be discarded in its entirety. Please help determine the largest number of cows FJ can milk without having to discard the milk.
输入
* Line 1: Three space-separated integers: N, D, and K
* Lines 2..N+1: Line i+1 describes the diseases of cow i with a list of 1 or more space-separated integers. The first integer, d_i, is the count of cow i‘s diseases; the next d_i integers enumerate the actual diseases. Of course, the list is empty if d_i is 0.
输出
* Line 1: M, the maximum number of cows which can be milked.
样例输入
6 3 2 0 1 1 1 2 1 3 2 2 1 2 2 1
样例输出
5
提示
OUTPUT DETAILS:
If FJ milks cows 1, 2, 3, 5, and 6, then the milk will have only two diseases (#1 and #2), which is no greater than K (2).
题意:有n头牛 d中病毒 如果牛感染超过k中病毒就视为不健康 求最多有多少头牛是健康的 ( 给你一些集合n,让你从中取一些集合求并,并之后集合的元素个数不能超过k。问你最多取多少集合。)
#include <cstdio> #include <queue> #include <cmath> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; const int oo = 0x3f3f3f3f; const int N = 200; const int M = 6000; typedef long long LL; struct da { int k; int die[50]; bool operator <(const da &a)const { return k < a.k; } }cow[1111]; int vis[1111], n, D, K, ans, dis[1111]; void dfs(int x, int sum, int maxs) { if(sum > K) return ; ans = max(ans, maxs); // if(x == n+1 && ans < maxs) ans = maxs; if(x > n)return ; for(int i = x; i <= n; i++) { if(vis[i] == 0) { vis[i] = 1; int cnt = 0; for(int j = 1; j <= cow[i].k; j++) { if(dis[cow[i].die[j]] == 0) cnt++; dis[cow[i].die[j]]++; } // if(sum+cnt <= K && maxs+1 > ans) ans = maxs + 1; //sum += cnt; dfs(i+1, sum+cnt, maxs+1); vis[i] = 0; // sum -= cnt; for(int j = 1; j <= cow[i].k; j++) dis[cow[i].die[j]]--; } } dfs(x+1, sum, maxs); } int main() { int i; while(~scanf("%d %d %d", &n, &D, &K)) { memset(vis, 0, sizeof(vis)); memset(dis, 0, sizeof(dis)); for(i = 1; i <= n; i++) { scanf("%d", &cow[i].k); for(int j = 1; j <= cow[i].k; j++) scanf("%d", &cow[i].die[j]); } ans = 0; sort(cow, cow+n); dfs(1, 0, 0); printf("%d\n", ans); } return 0; }
TLE!!!
TLE 了之后 借鉴了大神的想法换了种搜索的方式 很巧妙 我竟没想到(当选出的病毒数为K时,就遍历这N头牛,如果有牛所携带的病毒包含在K这些病毒里面 m++)
#include <cstdio> #include <queue> #include <cmath> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; const int oo = 0x3f3f3f3f; const int N = 200; const int M = 6000; typedef long long LL; struct da { int k; int die[50]; bool operator <(const da &a)const { return k < a.k; } } cow[1111]; int vis[1111], n, D, K, ans; void solve() { int i, j, mini = 0; for(i = 1; i <= n; i++) { for(j = 1; j <= cow[i].k; j++) { if(!vis[cow[i].die[j]])/**< 如果这头牛所感染的病毒没有出现过 这头牛就不能选 */ break; } if(j == cow[i].k+1) mini++;/**< 这头牛所携带的病毒都出现过 选上这头牛 */ } ans = max(ans, mini); } void dfs(int x, int sum) { if(sum == K)solve(); if(x > D) return ;/**< 递归结束边界 */ vis[x] = 1;/**< 标记数组 标记这个病毒是否出现过 */ dfs(x+1, sum+1); vis[x] = 0; dfs(x+1, sum); } int main() { int i; while(~scanf("%d %d %d", &n, &D, &K)) { memset(vis, 0, sizeof(vis)); for(i = 1; i <= n; i++) { scanf("%d", &cow[i].k); for(int j = 1; j <= cow[i].k; j++) scanf("%d", &cow[i].die[j]); } ans = 0; sort(cow, cow+n);/**< 貌似可以不排序 */ dfs(1, 0); printf("%d\n", ans); } return 0; }