深搜入门

问题描述

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;
}

  

时间: 2024-08-24 07:21:57

深搜入门的相关文章

hdu1010-Tempter of the Bone DFS深搜入门题+奇偶剪枝

Tempter of the Bone Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 69699    Accepted Submission(s): 19176 Problem Description The doggie found a bone in an ancient maze, which fascinated him a

NYoj 素数环(深搜入门)

题目链接: http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=488 深搜模板: 1 void dfs(int 当前状态) 2 { 3 if(当前状态为边界状态) 4 { 5 记录或输出 6 return; 7 } 8 for(i=0;i<n;i++) //横向遍历解答树所有子节点 9 { 10 //扩展出一个子状态. 11 修改了全局变量 12 if(子状态满足约束条件) 13 { 14 dfs(子状态) 15 } 16 恢复全局变量//回

POJ 2386 DFS深搜入门

Time Limit: 1000MS Memory Limit: 65536K Description Due to recent rains, water has pooled in various places in Farmer John's field, which is represented by a rectangle of N x M (1 <= N <= 100; 1 <= M <= 100) squares. Each square contains eithe

poj 1164 The Castle (入门深搜)

题目: 1 2 3 4 5 6 7 ############################# 1 # | # | # | | # #####---#####---#---#####---# 2 # # | # # # # # #---#####---#####---#####---# 3 # | | # # # # # #---#########---#####---#---# 4 # # | | | | # # ############################# (Figure 1)

深搜基础题目 杭电 HDU 1241

HDU 1241 是深搜算法的入门题目,递归实现. 原题目传送门: http://acm.hdu.edu.cn/showproblem.php?pid=1241 代码仅供参考,c++实现: #include <iostream> using namespace std; char land[150][150]; int p,q; void dfs(int x,int y){ land[x][y] = '*'; if(land[x-1][y]!= '@' && land[x+1]

hdu--1520--树形dp&lt;写起来就是深搜啊&gt;

我肯定还没怎么理解树形dp啊...为什么写下去 就感觉是多了个状态转移方程的深搜呢?或者因为树形dp是依托在树这个数据结构上所进行的 所以是这样的? 这题 被很多人 当做树形dp的入门题 的确.... 如果 u 是 v 的前驱即父母 那么 dp[u][0] += max( dp[v][1] , dp[v][0] ) 0表示u不包括在内 1在内 dp[u[[1] += dp[v][0] 不太难写 还好这个 主要是 每个树形dp都要找出根结点 因为数据很宽松 我直接用了vector来写 1 #inc

7.1 深搜-子集和问题 (枚举子集+剪枝)

---恢复内容开始--- 7.1,今日AC题目5到,今天为大家讲解一道普及组的深搜剪枝问题,这道题参解时需要在脑海及对应的手上模拟,切忌眼高手低,切忌三心二意 题目描述 对于一个给定正整数的集合s={x1,x2,x3…xn}和正整数c,编程计算s的第一个子集s1,使得子集s1的和等于c. 输入 第一行有2个正整数n和c 第二行有n个正整数 n<7000,c<maxlongint 输出 一行数据,按输入的顺序输出,若无解则输出"No Solution!" 样例输入 5 10

hdu1455 Sticks 深搜 强剪枝

Sticks Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6035    Accepted Submission(s): 1704 Problem Description George took sticks of the same length and cut them randomly until all parts becam

深搜笔记

看搜索已经很久了,对于搜索的思想从原来的死记硬背到现在终于懂了一点其实也蛮不错吧,我自己先总结出来了几条关于在图里面深搜的几条方法,仅供参考: 首先:我们得知道深搜是什么,其次于广搜的区别是什么.然后又哪些模板 举一个深搜例子:red and black:这是初学者最常见到的题.对于这题我们所要考虑的就是一个'.'的个数,这个题先要找到@的位置,这个好办,直接: for(int i=0;i<m;i++) { for(int j=0;j<n;j++) { if(map[i][j]=='@') }