2024-03-30:用go语言,集团里有 n 名员工,他们可以完成各种各样的工作创造利润, 第 i 种工作会产生 profit[i] 的利润,它要求 group[i] 名成员共同参与, 如果成员参与
2024-03-30:用go语言,集团里有 n 名员工,他们可以完成各种各样的工作创造利润,
第 i 种工作会产生 profit[i] 的利润,它要求 group[i] 名成员共同参与,
如果成员参与了其中一项工作,就不能参与另一项工作,
工作的任何至少产生 minProfit 利润的子集称为 盈利计划,
并且工作的成员总数最多为 n。
有多少种计划可以选择?因为答案很大,所以 返回结果模 10^9 + 7 的值。
输入:n = 5, minProfit = 3, group = [2,2], profit = [2,3]。
输出:2。
答案2024-03-30:
来自左程云。
大体步骤如下:
这三种算法都解决了一个问题,即在给定一组工作和利润以及员工的人数限制下,找出满足最低利润要求的盈利计划数量。以下是它们的大体过程:
profitableSchemes1:
1.递归函数 f1 对组合进行深度优先搜索,尝试每种工作的所有可能性,以达到满足最低利润要求的盈利计划。
2.检查每种工作是否满足人数限制,并计算利润是否达到最低要求。
3.返回满足条件的计划数量。
profitableSchemes2:
1.使用动态规划方法,创建三维数组 dp 以保存中间结果。
2.递归函数 f2 逐步填充 dp 数组,记录以当前工作和利润数为基础时的计划数量。
3.每次计算时检查数组中是否已有记录,避免重复计算。
4.返回最终计划数量。
profitableSchemes3:
1.同样采用动态规划,但只使用二维数组 dp,减少额外空间的使用。
2.从最后一个工作向前逐步计算满足条件的计划数量。
3.根据当前工作是否选择、人数是否足够、利润是否达标,更新动态规划数组中的值。
4.最终输出满足条件的计划数量。
复杂度分析:
时间复杂度:
profitableSchemes1: 由于是基于递归的深度优先搜索,时间复杂度较高,为指数级别,取决于工作数量和员工人数。
profitableSchemes2: 使用了动态规划并记录了每个可能情况,时间复杂度为 O(m * n * minProfit),m 为工作数量,n 为员工人数。
profitableSchemes3: 类似于第二种算法,但只使用了二维数组,时间复杂度也为 O(m * n * minProfit)。
空间复杂度:
profitableSchemes1: 仅有递归调用的栈空间,空间复杂度取决于递归深度。
profitableSchemes2: 使用了三维数组
dp,空间复杂度为 O(m * n * minProfit)。profitableSchemes3: 使用了二维数组
dp,空间复杂度为 O(n * minProfit)。
Go完整代码如下:
package main
import "fmt"
func profitableSchemes1(n int, minProfit int, group []int, profit []int) int {
return f1(group, profit, 0, n, minProfit)
}
func f1(g []int, p []int, i int, r int, s int) int {
if r <= 0 {
if s <= 0 {
return 1
} else {
return 0
}
}
if i == len(g) {
if s <= 0 {
return 1
} else {
return 0
}
}
p1 := f1(g, p, i+1, r, s)
p2 := 0
if g[i] <= r {
p2 = f1(g, p, i+1, r-g[i], s-p[i])
}
return p1 + p2
}
var mod = 1000000007
func profitableSchemes2(n int, minProfit int, group []int, profit []int) int {
m := len(group)
dp := make([][][]int, m)
for a := 0; a < m; a++ {
dp[a] = make([][]int, n+1)
for b := 0; b <= n; b++ {
dp[a][b] = make([]int, minProfit+1)
for c := 0; c <= minProfit; c++ {
dp[a][b][c] = -1
}
}
}
return f2(group, profit, 0, n, minProfit, dp)
}
func f2(g []int, p []int, i int, r int, s int, dp [][][]int) int {
if r <= 0 {
if s == 0 {
return 1
} else {
return 0
}
}
if i == len(g) {
if s == 0 {
return 1
} else {
return 0
}
}
if dp[i][r][s] != -1 {
return dp[i][r][s]
}
p1 := f2(g, p, i+1, r, s, dp)
p2 := 0
if g[i] <= r {
p2 = f2(g, p, i+1, r-g[i], max(0, s-p[i]), dp)
}
ans := (p1 + p2) % mod
dp[i][r][s] = ans
return ans
}
func max(x, y int) int {
if x > y {
return x
}
return y
}
func profitableSchemes3(n int, minProfit int, group []int, profit []int) int {
dp := make([][]int, n+1)
for r := 0; r <= n; r++ {
dp[r] = make([]int, minProfit+1)
dp[r][0] = 1
}
m := len(group)
for i := m - 1; i >= 0; i-- {
for r := n; r >= 0; r-- {
for s := minProfit; s >= 0; s-- {
p1 := dp[r][s]
p2 := 0
if group[i] <= r {
p2 = dp[r-group[i]][max(0, s-profit[i])]
}
dp[r][s] = (p1 + p2) % mod
}
}
}
return dp[n][minProfit]
}
func main() {
n := 5
minProfit := 3
group := []int{2, 2}
profit := []int{2, 3}
result1 := profitableSchemes1(n, minProfit, group, profit)
fmt.Println("Result using profitableSchemes1:", result1)
result2 := profitableSchemes2(n, minProfit, group, profit)
fmt.Println("Result using profitableSchemes2:", result2)
result3 := profitableSchemes3(n, minProfit, group, profit)
fmt.Println("Result using profitableSchemes3:", result3)
}

2024-03-30:用go语言,集团里有 n 名员工,他们可以完成各种各样的工作创造利润, 第 i 种工作会产生 profit[i] 的利润,它要求 group[i] 名成员共同参与, 如果成员参与的更多相关文章
- static数据成员与const数据成员的定义与初始化
三种数据类型的初始化 1.static int a 的初始化 const int a 的初始化 static const int a的初始化 三种初始化方式 在类外初始化 在构造函数中通过初始化列表初 ...
- 不可或缺 Windows Native (21) - C++: 继承, 组合, 派生类的构造函数和析构函数, 基类与派生类的转换, 子对象的实例化, 基类成员的隐藏(派生类成员覆盖基类成员)
[源码下载] 不可或缺 Windows Native (21) - C++: 继承, 组合, 派生类的构造函数和析构函数, 基类与派生类的转换, 子对象的实例化, 基类成员的隐藏(派生类成员覆盖基类成 ...
- 【转载】C++ 与“类”有关的注意事项总结(十二):按成员初始化 与 按成员赋值
原文:C++ 与"类"有关的注意事项总结(十二):按成员初始化 与 按成员赋值 一.按成员初始化(与构造函数和拷贝构造函数有关) 用一个类对象初始化另一个类对象,比如: Accou ...
- [C]成员运算符"."和间接成员运算符"->"浅析
成员运算符: . 成员运算符一般和结构或者联合名一起使用,指定结构或者联合中的某个成员. 举个栗子: 如果Ronz是一个结构的名称,linux是这个结构模板指定的一个成员名. struct{ //匿名 ...
- Java中变量之局部变量、本类成员变量、父类成员变量的访问方法
变量:局部变量.本类成员变量.父类成员变量 如何访问:如果变量名相同,则采用就近原则,哪个变量离所要调用的访问最近,那就么就输出,优先顺序为:局部变量 > 本类成员变量 > 父类成员变量 ...
- C++类中的常数据成员和静态数据成员的区别
刚开始学习C++的类和对象的部分,对类中的常数据成员和静态数据成员的概念和用法经常混淆,所以今天整理一下,顺便说一下,今天是我的生日,祝我生日快乐,呵呵. 常数据成员 常数据成员是指在类中定义的不能修 ...
- OJ提交题目中的语言选项里G++与C++的区别(转)
G++? 首先更正一个概念,C++是一门计算机编程语言,G++不是语言,是一款编译器中编译C++程序的命令而已. 那么他们之间的区别是什么? 在提交题目中的语言选项里,G++和C++都代表编译的方式. ...
- 类中成员函数与数据成员private/pubic/protected
类中成员函数与数据成员private/pubic/protected
- OJ提交题目中的语言选项里G++与C++的区别(转载)
原文链接:http://blog.polossk.com/201405/c-plus-plus-g-plus-plus G++? 首先更正一个概念,C++是一门计算机编程语言,G++不是语言,是一款编 ...
- C++ static成员变量与static成员函数
类中的静态成员真是个让人爱恨交加的特性.我决定好好总结一下静态类成员的知识点,以便自己在以后面试中,在此类问题上不在被动. 静态类成员包括静态数据成员和静态函数成员两部分. 一 静态数据成员: 类 ...
随机推荐
- CSS实现页脚始终在页面底部
说明 最近在布局自己的博客系统,我是想练练手把时下比较流行的前后端技术串起来.同时,我会把设计和编码过程中遇到的问题或值得分享的技术点.实现方式做下总结,记录下来.本篇就是第一篇,个人能力有限,不足之 ...
- CSDN的Markdown编辑器使用说明
这里写自定义目录标题 欢迎使用Markdown编辑器 新的改变 功能快捷键 合理的创建标题,有助于目录的生成 如何改变文本的样式 插入链接与图片 如何插入一段漂亮的代码片 生成一个适合你的列表 创建一 ...
- AI数字人SadTalker实战
1.概述 AI数字人在营销和品牌推广中扮演着至关重要的角色,许多企业和个人正积极利用数字技术来打造属于自己的财富.有没有一种简单而免费的方式来创建自己的数字人呢?本篇博客笔者将为大家介绍如何搭建属于自 ...
- Mysql 插入timestamp没有使用默认值问题
在一次升级过程中,发现Mysql插入数据报了个错 Column 'create_time' cannot be null. 但是看了下这个字段虽然是非null,但是是有默认值的 `create_tim ...
- 麒麟系统开发笔记(十一):在国产麒麟系统上使用gdb定位崩溃异常方法流程进阶定位代码行数及专项测试Demo
前言 上一篇,通过研究,可以定位到函数,本篇进一步优化,没有行数,程序较为复杂的时候,就无法定位,所以进一步定位. 本篇做了qBreakpad的研究,但是没有成功,过程也还是填出来,后来突然注意 ...
- 【Azure 事件中心】开启 Apache Flink 制造者 Producer 示例代码中的日志输出 (连接 Azure Event Hub Kafka 终结点)
问题描述 Azure Event Hub 在标准版以上就默认启用的Kafka终结点,所以可以通过Apache Kafka协议连接到Event Hub进行消息的生产和消费.通过示例代码下载到本地运行后, ...
- 别再低效筛选数据了!试试pandas query函数
数据过滤在数据分析过程中具有极其重要的地位,因为在真实世界的数据集中,往往存在重复.缺失或异常的数据.pandas提供的数据过滤功能可以帮助我们轻松地识别和处理这些问题数据,从而确保数据的质量和准确性 ...
- Java 多态 案列
1 package com.bytezreo.duotai; 2 3 //多态性的使用 举例一 4 public class AnimalTest 5 { 6 public static void m ...
- Java this关键字使用 详解+ 证明
1 package com.bytezero.thistest; 2 /** 3 * 4 * @Description 5 * @author Bytezero·zhenglei! Email:420 ...
- Java 从键盘输入不确定的整数 并判断读入的整数和负数的个数,输入0时候结束
1 /** 2 * 从键盘输入不确定的整数 并判断读入的整数和负数的个数,输入0时候结束 3 * 4 */ 5 6 Scanner scan = new Scanner(System.in); 7 8 ...