200字
小明减肥
2025-12-06
2025-12-06

题目

小明有n个可选运动,每个运动有对应卡路里,想选出其中k个运动且卡路里和为t。k,t,n都是给定的。求出可行解数量

输入描述

第一行输入n t k

第二行输入 每个运动的卡路里 按照空格进行分割

备注

0<n<10

t>0,0<k<=n

每个运动量的卡路里>0

输出描述

求出可行解数量

示例1:

输入

4 3 2

1 1 2 3

输出

2

说明

可行解为2,选取{0,2},{1,2}两种方式。

def find_data():
    n, t, k = map(int,input().split())
    nums = list(map(int,input().split()))
    count_sum = 0
    def backstack(start,count,sums):
        nonlocal count_sum
        if count>k:
            return
        if sums >t:
            return
        # 剩余元素不足以选满k个
        if count + (n - start) < k:
            return
        if sums ==t and  count==k:
            count_sum+=1
            return
        for i in range(start,n):
            backstack(i+1,count+1,sums+nums[i])
    backstack(0,0,0)
    return count_sum

if __name__ == '__main__':
    print(find_data())

这个回溯算法的逻辑是寻找数组中满足特定条件的子集个数。让我总结一下核心逻辑:

算法目标

从n个元素的数组中,找出所有恰好包含k个元素且元素和为t的子集个数。

核心逻辑

1. 参数设计

  • start: 当前搜索的起始索引(避免重复组合)

  • count: 已选择的元素个数

  • sums: 已选择元素的和

2. 剪枝策略(关键优化)

python

# 1. 元素个数超过k → 剪枝
if count > k: return

# 2. 元素和超过t → 剪枝  
if sums > t: return

# 3. 剩余元素不足以选满k个 → 剪枝
if count + (n - start) < k: return

3. 终止条件

python

if sums == t and count == k:  # 找到有效解
    count_sum += 1
    return

4. 搜索过程

  • start开始遍历数组

  • 每次选择nums[i],递归搜索下一个位置i+1

  • 采用组合搜索而非排列搜索(通过start参数保证)

算法特点

  1. 组合问题:顺序无关([1,2]和[2,1]视为相同)

  2. 精确匹配:要求元素个数恰好为k,和恰好为t

  3. 深度优先搜索:递归探索所有可能组合

  4. 多重剪枝:有效减少不必要的搜索

时间复杂度

  • 最坏情况:O(C(n,k)),即从n个元素中选k个的所有组合

  • 实际由于剪枝,通常远小于理论值

适用场景

适合解决子集和问题的变体,特别是在n不大(通常n≤30)且需要精确匹配元素个数和总和的情况下。

这是一个典型的回溯+剪枝算法实现,平衡了穷举的完整性和效率优化。

回溯法是一种解决问题的算法框架,用于寻找问题的所有解最优解

核心思想尝试所有可能的选项,如果发现当前路径不可能得到解,就回退一步,尝试其他选项

关键特征

  1. 做出选择

  2. 递归探索

  3. 撤销选择(回退到之前的状态)

  4. 剪枝(提前终止不可能得到解的路径)

回溯法模板

python

def backtrack(路径, 选择列表):
    if 满足结束条件:
        结果.append(路径.copy())  # 注意要复制
        return
    
    for 选择 in 选择列表:
        # 做选择
        路径.append(选择)
        从选择列表中移除该选择  # 可选
        
        # 剪枝:如果选择不合法,跳过
        if not is_valid(选择):
            路径.pop()  # 撤销选择
            continue
            
        # 递归
        backtrack(路径, 选择列表)
        
        # 撤销选择(回溯的核心)
        路径.pop()


小明减肥
作者
Shisuiyi
发表于
2025-12-06
License
CC BY-NC-SA 4.0

评论