深搜入门

问题描述

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

  

转载于:https://www.cnblogs.com/PersistFaith/p/4819914.html

<think>好的,用户想了解度优先索算法的实现。首先,我需要回顾一下DFS的基本原理。DFS是一种用于遍历或索树或图的算法,沿着分支入到底,再回溯继续探索其他分支。根据用户的引用资料,实现方式主要有递归和栈两种方法。 接下来,我需要整理实现步骤。对于递归实现,需要标记已访问节点,然后递归访问相邻节点。栈的实现则是手动维护一个栈结构,循环处理直到栈空。还要注意不同编程语言的实现差异,比如Python可能用列表模拟栈,而C++或C可能用数组或标准库的栈结构。 然后,用户提供的引用中有不同语言的例子,比如C语言用邻接矩阵,Python用递归,C++用栈解决迷宫问题。需要比较这些实现方式的异同,指出核心思想一致,但数据结构选择可能影响具体实现。例如,迷宫问题中用栈记录路径,而图遍历可能用邻接表或矩阵存储节点关系。 还要考虑用户可能遇到的问题,比如栈溢出风险,如何处理非连通图,以及如何标记已访问节点防止重复。此外,性能方面,DFS的时间复杂度是O(V+E),空间复杂度在最坏情况下是O(V),尤其是当使用递归时,度过大会导致栈溢出,这时候栈的实现方式可能更优。 最后,根据引用资料,用户可能需要实际应用的例子,比如解决迷宫问题或拓扑排序。需要确保回答覆盖递归和栈两种实现方式,并提供代码示例,同时引用相关的参考资料。此外,生成的问题要围绕实现细节、优化、应用场景等方面,帮助用户进一步学习。</think>### 度优先索算法实现解析 度优先索(DFS)通过递归回溯或显式栈结构实现图的遍历,核心特征是优先探索最层的节点。以下分步骤说明实现要点: #### 一、核心实现方式 1. **递归实现** ```python def dfs_recursive(graph, node, visited): if node not in visited: print(node) # 访问节点 visited.add(node) for neighbor in graph[node]: dfs_recursive(graph, neighbor, visited) ``` - 时间复杂度:$O(V+E)$(V为顶点数,E为边数)[^2] - 空间复杂度:$O(V)$(递归调用栈度) 2. **栈迭代实现** ```python def dfs_stack(graph, start): visited = set() stack = [start] while stack: node = stack.pop() if node not in visited: print(node) # 访问节点 visited.add(node) stack.extend(reversed(graph[node])) # 保证访问顺序与递归一致 ``` #### 二、关键实现细节 1. **访问标记机制** - 必须使用集合/数组记录已访问节点,防止重复遍历 - 迷宫问题中常用二维数组标记路径[^4] 2. **邻接结构选择** - 邻接矩阵:空间复杂度$O(V^2)$,适合稠密图 - 邻接表:空间复杂度$O(V+E)$,适合稀疏图[^1] 3. **路径记录方法** - 迷宫求解时需用栈保存当前路径[^4] - 拓扑排序需记录后序访问顺序 #### 三、典型应用场景 1. 连通分量检测 2. 迷宫路径索(示例见引用[4]) 3. 拓扑排序 4. 回溯法求解组合问题 ```cpp // C++迷宫路径索核心代码片段 void DFS_Maze(int x, int y) { stack<pair<int, int>> path; path.push(make_pair(x, y)); while (!path.empty()) { auto current = path.top(); // 判断终点及方向拓展逻辑 } } ``` #### 四、注意事项 1. 递归度超过系统限制时需改用迭代实现 2. 非连通图需遍历所有未访问节点 3. 加权图中DFS不能保证找到最短路径
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值