[递归,动态规划] 和为定值的子集合

2023-11-26 11:36

本文主要是介绍[递归,动态规划] 和为定值的子集合,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

和为定值的子集数

题目描述

已知 n 个正整数,wi  (1≤i≤n) 形成一个集合 W={w1,w2,...,wn},集合中的元素彼此不相同。给定某个正整数 M ,集合W中可否存在子集,该子集的所有元素之和和恰好为M,问:这样的子集有多少个?
例如,4个正整数为:
11 13 24 7
若给定M=31,则有两个子集{7,11,13}和{7,24}
于是,这样的子集有 2 个。

关于输入

第1行,输入若干个正整数,表示集合的元素,各整数之间以空格间隔;
后面有多行,每行表示一个 M 值;若某行的 M 值为0,则结束。

关于输出

对应的每个有效的 M 值,输出相应行的子集数目

例子输入
11 13 24 7
31
24
45
55
0
例子输出
2
2
0
1
解题分析

这个问题可以使用动态规划(Dynamic Programming)来解决。动态规划是一种在数学、计算机科学和经济学中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。

在这个问题中,我们需要找到所有和为特定值 M 的子集的数量。我们可以使用一个二维动态规划数组 dp[i][j] 来存储到第 i 个元素为止,和为 j 的子集的数量。

这个问题的状态转移方程可以这样定义:

1. 如果当前集合的总和 M 为0,那么只有一个子集满足条件,即空子集,所以返回1。
2. 如果我们已经查看过所有的元素(i < 0),或者当前的总和 M 为负数,那么没有子集满足条件,返回0。
3. 如果当前元素 a[i] 大于当前的总和 M,那么我们不能包含这个元素,所以只能查看前 i-1 个元素,看看他们能否组成和为 M 的子集。所以 dp[i][M] = sum(i-1, M)。
4. 如果当前元素 a[i] 小于或等于当前的总和 M,那么我们有两种选择:包含这个元素或者不包含这个元素。所以 dp[i][M] = sum(i-1, M) + sum(i-1, M-a[i])。

在主函数中,我们首先使用一个循环来读取输入的元素,并将它们存储在数组 a 中。然后,我们使用另一个循环来读取输入的 M 值,并调用 sum 函数来计算满足条件的子集的数量。最后,我们将结果输出到屏幕上。

注意,为了提高效率,我们使用了记忆化搜索(也称为缓存)。我们使用一个二维数组 dp 来存储已经计算过的子问题的结果。在 sum 函数中,我们首先检查 dp[i][M] 是否已经被计算过。如果是,我们就直接返回它。否则,我们就计算它,然后将结果存储在 dp[i][M] 中,以便以后使用。

这种方法的时间复杂度是 O(n*M),其中 n 是集合的元素数量,M 是目标和。空间复杂度也是 O(n*M),用于存储 dp 数组。

代码实现
#include <iostream>
#include <cstring>
using namespace std;int M, a[10000];
int len = 0;
int dp[10000][10000]={0};int sum(int i, int M) {if (M == 0) return 1;if (i < 0 || M < 0) return 0;if(dp[i][M]!=-1) return dp[i][M];if (a[i] > M) {dp[i][M]=sum(i-1,M);return dp[i][M];} else {dp[i][M]=sum(i - 1, M) + sum(i - 1, M - a[i]);return dp[i][M];}
}int main() {char c;memset(dp,-1,sizeof(dp));while (cin >> a[len++]) {c = getchar();if (c == '\n') break;}while (cin >> M) {if (M == 0) break;cout << sum(len - 1, M) << endl;}return 0;
}

方法2:

解题分析2

这个问题可以使用动态规划来解决。我们可以构建一个二维数组dp,其中dp[i][j]表示使用前i个数字组成和为j的子集的数量。

初始条件是dp[i][0] = 1,表示使用前i个数字组成和为0的子集只有一种可能,即一个空集。然后我们可以根据以下状态转移方程来填充dp数组:

dp[i][j] = dp[i - 1][j] + dp[i - 1][j - nums[i - 1]], 如果 j >= nums[i - 1]
dp[i][j] = dp[i - 1][j], 如果 j < nums[i - 1]

其中nums[i - 1]表示第i个数字。第一个条件表示我们可以选择包含第i个数字或者不包含第i个数字,第二个条件表示如果当前的和j小于第i个数字,那么我们不能选择第i个数字。

这个算法的时间复杂度是O(n * M),空间复杂度也是O(n * M),其中n是集合中的数字数量,M是给定的目标和。

#include <iostream>
#include <cstring>
using namespace std;int M, a[10000];
int len = 0;
int dp[10000][10000]={0};int main() {char c;while (cin >> a[len++]) {c = getchar();if (c == '\n') break;}while (cin >> M) {if (M == 0) break;for(int i=0;i<len;i++){dp[i][0]=1;}for(int i=0;i<len;i++){for(int j=1;j<=M;j++){if(i==0){if(a[i]==j){dp[i][j]=1;}continue;}if(a[i]>j){dp[i][j]=dp[i-1][j];}else{dp[i][j]=dp[i-1][j]+dp[i-1][j-a[i]];}}}cout<<dp[len-1][M]<<endl;}return 0;
}

这篇关于[递归,动态规划] 和为定值的子集合的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/425615

相关文章

Java调用C#动态库的三种方法详解

《Java调用C#动态库的三种方法详解》在这个多语言编程的时代,Java和C#就像两位才华横溢的舞者,各自在不同的舞台上展现着独特的魅力,然而,当它们携手合作时,又会碰撞出怎样绚丽的火花呢?今天,我们... 目录方法1:C++/CLI搭建桥梁——Java ↔ C# 的“翻译官”步骤1:创建C#类库(.NET

MyBatis编写嵌套子查询的动态SQL实践详解

《MyBatis编写嵌套子查询的动态SQL实践详解》在Java生态中,MyBatis作为一款优秀的ORM框架,广泛应用于数据库操作,本文将深入探讨如何在MyBatis中编写嵌套子查询的动态SQL,并结... 目录一、Myhttp://www.chinasem.cnBATis动态SQL的核心优势1. 灵活性与可

Mybatis嵌套子查询动态SQL编写实践

《Mybatis嵌套子查询动态SQL编写实践》:本文主要介绍Mybatis嵌套子查询动态SQL编写方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录前言一、实体类1、主类2、子类二、Mapper三、XML四、详解总结前言MyBATis的xml文件编写动态SQL

SpringBoot实现Kafka动态反序列化的完整代码

《SpringBoot实现Kafka动态反序列化的完整代码》在分布式系统中,Kafka作为高吞吐量的消息队列,常常需要处理来自不同主题(Topic)的异构数据,不同的业务场景可能要求对同一消费者组内的... 目录引言一、问题背景1.1 动态反序列化的需求1.2 常见问题二、动态反序列化的核心方案2.1 ht

golang实现动态路由的项目实践

《golang实现动态路由的项目实践》本文主要介绍了golang实现动态路由项目实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习... 目录一、动态路由1.结构体(数据库的定义)2.预加载preload3.添加关联的方法一、动态路由1

Python Selenium动态渲染页面和抓取的使用指南

《PythonSelenium动态渲染页面和抓取的使用指南》在Web数据采集领域,动态渲染页面已成为现代网站的主流形式,本文将从技术原理,环境配置,核心功能系统讲解Selenium在Python动态... 目录一、Selenium技术架构解析二、环境搭建与基础配置1. 组件安装2. 驱动配置3. 基础操作模

mysql递归查询语法WITH RECURSIVE的使用

《mysql递归查询语法WITHRECURSIVE的使用》本文主要介绍了mysql递归查询语法WITHRECURSIVE的使用,WITHRECURSIVE用于执行递归查询,特别适合处理层级结构或递归... 目录基本语法结构:关键部分解析:递归查询的工作流程:示例:员工与经理的层级关系解释:示例:树形结构的数

慢sql提前分析预警和动态sql替换-Mybatis-SQL

《慢sql提前分析预警和动态sql替换-Mybatis-SQL》为防止慢SQL问题而开发的MyBatis组件,该组件能够在开发、测试阶段自动分析SQL语句,并在出现慢SQL问题时通过Ducc配置实现动... 目录背景解决思路开源方案调研设计方案详细设计使用方法1、引入依赖jar包2、配置组件XML3、核心配

springboot使用Scheduling实现动态增删启停定时任务教程

《springboot使用Scheduling实现动态增删启停定时任务教程》:本文主要介绍springboot使用Scheduling实现动态增删启停定时任务教程,具有很好的参考价值,希望对大家有... 目录1、配置定时任务需要的线程池2、创建ScheduledFuture的包装类3、注册定时任务,增加、删

SpringBoot基于配置实现短信服务策略的动态切换

《SpringBoot基于配置实现短信服务策略的动态切换》这篇文章主要为大家详细介绍了SpringBoot在接入多个短信服务商(如阿里云、腾讯云、华为云)后,如何根据配置或环境切换使用不同的服务商,需... 目录目标功能示例配置(application.yml)配置类绑定短信发送策略接口示例:阿里云 & 腾