搜索-dfs

本文介绍了深度优先搜索(DFS)在解决将数字拆分成多个正整数的问题中的应用,包括n重循环的实现和剪枝优化策略,通过两个例题(4124分糖果和3505买瓜)展示了如何用DFS解决此类问题并降低计算复杂度。
摘要由CSDN通过智能技术生成

DFS简介

搜索算法:

穷举问题解空间部分/所有情况,从而求出问题的解

深度优先搜索:

本质上是暴力枚举

深度优先:尽可能一条路走到底,走不了再回退

在这里插入图片描述

DFS和n重循环

给定一个数字x,将其拆分成3个正整数,后一个要求大于等于前一个,给出方案。

简单思想:三重循环暴力求解

那么,拆分成4个正整数?n个正整数呢?

需要实现n重循环
n重循环 = 特定的树状结构 = DFS搜索

给定一个数字x=6,将其拆分成3个正整数,后一个要求大于等于前一个,给出方案。
在这里插入图片描述
给定一个数字x,将其拆分成n个正整数,后一个要求大于等于前一个,给出方案。

n重循环:n层的树
DFS:从上往下找一条合法的路径(路径值不递减,长度为n,和为x

在这里插入图片描述

def dfs(depth):
    """
    :param depth: 当前是第几重循环
    :return:
    """
    global cnt
    cnt = cnt + 1
    if depth == n:
        for i in range(1,n):
            if a[i] >= a[i-1]:
                continue
            else:
                return
        if sum(a) != x:
            return
        print(a)
        return
    for i in range(1,x+1):
        a[depth] = i
        dfs(depth+1)


x , n = map(int,input().split())
a = [0] * n
cnt = 0

dfs(0)
print("累计计算次数={}".format(cnt))

把条件放在枚举的时候判断可以降低计算量:剪枝

def dfs(depth,last_val):
    global cnt
    if depth == n:
        if sum(a) != x:
            return
        print(a)
        return 
    for i in range(last_val,x+1):
        a[depth] = i
        dfs(depth+1,i)



x , n = map(int,input().split())
a = [0] * n
cnt = 0

# dfs(0)
dfs(0,1)
print("累计计算次数={}".format(cnt))

例题

题目链接:4124分糖果

4124分糖果

ans = 0
def dfs(depth,n,m):
    """
    :param depth:第depth个小朋友
    :param n: 第一类糖果数量
    :param m: 第二类糖果数量
    :return:
    """
    if depth == 7:
        if n == 0 and m == 0:
            global ans
            ans += 1
        return
    for i in range(0,6):
        for j in range(0,6):
            if 2 <= i+j <= 5 and i <= n and j <= m:
                dfs(depth+1,n-i,m-j)

dfs(0,9,16)
print(ans)

运行结果

5067671

题目链接:3505买瓜

3505买瓜

def dfs(depth,s,cnt):
    """
    :param depth: 第depth层循环
    :param s: 当前累计的重量
    :param cnt: 当前劈的西瓜个数
    :return:
    """
    if s > m :
        return
    if s == m :
        global ans
        ans = min(ans,cnt)
    if depth == n:
        return
    #买一个
    dfs(depth + 1 , s + w[depth] , cnt)
    # 买半个
    dfs(depth + 1, s + w[depth] // 2, cnt+1)
    # 不买
    dfs(depth + 1, s, cnt)


n , m = map(int,input().split())
m *= 2
w = list(map(int,input().split()))
w = [x * 2 for x in w]

ans = n+1
dfs(0,0,0)
if ans == n+1:
    ans = -1

print(ans)

运行结果

3 10
1 3 13


2
这个有趣的说法似乎是在引用网络流行语,但它并不是一个直接的编程题目。然而,如果你想要了解如何用C语言实现深度优先搜索DFS),这是一个经典的图遍历算法,可以模拟查找两个节点之间的路径。以下是使用DFS的一个简单示例,假设我们有一个无向图,用邻接表表示: ```c #include <stdio.h> #include <stdlib.h> typedef struct Node { int value; struct Node* next; } Node; void DFS(Node** graph, int start, int goal) { Node* current = *graph[start]; while (current != NULL) { if (current->value == goal) { printf("找到了! %d -> %d\n", start, goal); return; } // 递归遍历当前节点的所有邻居 DFS(graph, current->value, goal); current = current->next; } printf("未找到路径从 %d 到 %d\n", start, goal); } // 添加边到邻接表 void addEdge(Node** graph, int src, int dst) { Node* newNode = (Node*)malloc(sizeof(Node)); newNode->value = dst; newNode->next = graph[src]; graph[src] = newNode; } int main() { int n; // 图的节点数 printf("请输入节点数:"); scanf("%d", &n); Node** graph = (Node**)malloc(n * sizeof(Node*)); for (int i = 0; i < n; ++i) { graph[i] = NULL; } // 根据输入添加边 for (int i = 0; i < n - 1; ++i) { int u, v; printf("请输入边 (%d, %d): ", i + 1, i + 2); scanf("%d %d", &u, &v); addEdge(&graph[u - 1], v - 1, i + 1); // 减一操作将用户输入转换为数组索引 } int start, end; printf("请输入开始节点和目标节点:"); scanf("%d %d", &start, &end); DFS(graph, start - 1, end - 1); // 再次减一处理用户输入 return 0; } ``` 这个程序首先创建一个邻接表来存储图,然后根据用户的输入添加边,并执行深度优先搜索来查找指定起点和终点之间的路径。请注意,这里的"失散多年的兄妹"是一个比喻,实际上这里我们在找路径。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

唐丶晚笙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值