算法通关村第十九关:白银挑战-动态规划高频问题

news2024/11/28 5:35:36

白银挑战-动态规划高频问题

1. 最少硬币数

LeetCode 322
https://leetcode.cn/problems/coin-change/description/

思路分析

尝试用回溯来实现
假如coins=[2,5,7],amount=27,求解过程中,每个位置都可以从[2,5,7]中选择,因此可以逐步将所有情况枚举出来,然后再找到要求的最少硬币数,图示如下:
在这里插入图片描述

通过上面的图,发现 f[20] 等已经存在多次重复计算了,存在大量重复计算的问题,效率低。

尝试用贪心来实现
直觉告诉我们尽量使用大的,假如coins=[2,5,7],amount=27
先连续用 7+7+7=21,剩下6用2+2+2=6,一共 7+7+7+2+2+2=27,共使用了6枚硬币
但我们可以使用 7+5+5+5+5=27,使用5枚硬币就够了
贪心的思路不能解决本题

尝试用DP来实现
使用DP能同时满足效率和准确性

设状态f(x),最少用f(x)枚硬币能拼出x
建立数组arr,索引表示的是 amount,表示最少需要arr[i]个硬币能拼出来
其中有些位放的是M,表示就是不能拼出来的意思

coins = [1,2,5] 时
在这里插入图片描述

coins = [2,5,7] 时
在这里插入图片描述

以coins=[2,5,7],详细分析一步步实现DP

第一步:确定状态和子问题

状态
f(x),最少用f(x)枚硬币能拼出x

子问题
先看最后一步,从后向前找递归

  • 最优策略K枚硬币,a1, a2, … ak 面值加起来是27
  • 除掉最后一枚硬币ak,前面硬币加起来面值就是 27-ak
  • ak一定是 2,5,7 中的一枚
    • 如果ak=2,f(27)=f(25)+1
    • 如果ak=5,f(27)=f(22)+1
    • 如果ak=7,f(27)=f(20)+1
  • f(27)=min(f(25),f(22),f(20))+1

在这里插入图片描述

f(27)=min(f(25),f(22),f(20))+1
接下来,根据递归的思想再去算 f(25),f(22),f(20)…

其中f(6)=min(f(4),f(1),f(-1))+1
f(1)和f(-1)不满足要求,需要设置为正无穷
f(4)=2,f(6)=2+1=3

总结:递推要从右向左,计算要从左向右

第二步:确定状态转移方程

子问题确定之后,状态转移方程也基本确定了
在这里插入图片描述

f(x) = min(f(x-2), f(x-5), f(x-7)) + 1

第三步:确定初始条件和边界

初始条件 f(0) = 0
如果不能拼出x,就定义f(x)为正无穷

注意溢出问题:
如果不能拼定义为正无穷,可能存在溢出问题
可以用amount来代替正无穷

第四步:按顺序计算

执行状态转移方程 f(x) = min(f(x-2), f(x-5), f(x-7)) + 1 对数组进行计算
递推要从右向左,计算要从左向右

第五步:代码实现

第一版代码

# 伪代码
def coin(coins, amount):
    max_num = amount + 1
    dp = [max_num] * (amount + 1)
    dp[0] = 0
    for i in range(amount + 1):
        if check(i):
            dp[i] = min(dp[i - coins[0]], dp[i - coins[1]], dp[i - coins[2]]) + 1
    return dp[amount] if dp[amount] < max_num else -1


def check(i, coins):
    # 这里要保证 i - coins[i] 大于0
    # 这里还要保证不越界,写起来比较复杂,我们理解功能即可
    pass
    

第二版代码

# 伪代码
def coin(coins, amount):
    max_num = amount + 1
    dp = [max_num] * (amount + 1)
    dp[0] = 0
    for i in range(amount + 1):
        if check(i):
            dp[i] = min(dp[i], dp[i - coins[0]] + 1)
            dp[i] = min(dp[i], dp[i - coins[1]] + 1)
            dp[i] = min(dp[i], dp[i - coins[2]] + 1)
    return dp[amount] if dp[amount] < max_num else -1


def check(i, coins):
    # 这里要保证 i - coins[i] 大于0
    # 这里还要保证不越界,写起来比较复杂,我们理解功能即可
    pass

如果 coins[] 数组比较大,if判断就非常长,考虑价格循环解决,最终代码实现如下

第三版代码

class Solution:
    def coinChange(self, coins: List[int], amount: int) -> int:
        max_num = amount + 1
        dp = [max_num] * (amount + 1)
        dp[0] = 0
        for i in range(1, amount + 1):
            for j in range(len(coins)):
                if i - coins[j] >= 0:
                    dp[i] = min(dp[i], dp[i - coins[j]] + 1)
        return dp[amount] if dp[amount] < max_num else -1

总结一下求最值型DP的步骤

  1. 确定状态和子问题。
    从最后一步开始(最优策略中使用的最后一枚硬币ak)推导f(n)与子问题之间的关系,然后将其化成子问题(最少的硬币拼出更小的面值27-ak)

  2. 通过状态,可以得到状态转移方程 f(x) = min(f(x-2), f(x-5), f(x-7)) + 1

  3. 处理初始条件和边界问题。f[0]=0,其他如果不能拼出来标记为 f(x)=正无穷

  4. 从小到大开始计算。这里就是从 f(0),f(1),f(2)…向后计算

2. 最长连续递增子序列

LeetCode 674
https://leetcode.cn/problems/longest-continuous-increasing-subsequence/description/

思路分析

不用动态规划也能解决,例如前面介绍的滑动窗口就可以

动态规划解决

在这里插入图片描述

第一步:分析状态和子问题
状态 f(i) ,以a[i]结尾的最长连续上升子序列的长度

最后一个元素a[j],存在两种情况

  1. a[j]<=a[j-1],f[j]=1 (a[j]<=a[j-1] or j=0)
  2. a[j]>a[j-1],f[j] = f[j-1]+1 (j>0且a[j]>a[j-1])

第二步:转移方程
f[j]=1 a[j]<=a[j-1] or j=0)
f[j] = f[j-1]+1 j>0且a[j]>a[j-1]

第三步:初始条件和边界
f[j]=1 a[j]<=a[j-1] or j=0)
f[j] = f[j-1]+1 j>0且a[j]>a[j-1]

第四步:按照顺序计算
和硬币组合不一样,答案为 max([f(0), f(1), f(2), … ,f(n-1)])

代码实现

class Solution:
    def findLengthOfLCIS(self, nums: List[int]) -> int:
        # 动态规划
        arr = [1] * len(nums)
        for i in range(1, len(nums)):
            if nums[i] > nums[i-1]:
                arr[i] = arr[i-1] + 1
        return max(arr)

3. 最长递增子序列

LeetCode 300
https://leetcode.cn/problems/longest-increasing-subsequence/description/、

思路分析

本题与上一题 LeetCode 674 的区别:没有说子序列元素一定是连续的

在这里插入图片描述

使用DP解决问题的方法

第一步:确定状态和子问题
状态f(x) 第x个元素的最长递增子序列长度,求以a[x]结尾的最长上升子序列

子问题:
情况1:最长上升子序列为 { a[j] },f[j] = 1
情况2:最长上升子序列大于1
0<=i<j,a[j]>a[i],f[j] = f[i]+1
在这里插入图片描述

因为不确定最优策略中a[j]前一个元素a[i]是哪一个,需要枚举每个i,求以a[j]结尾的最长上升子序列
在这里插入图片描述

第二步:初始条件和边界
f[0] = 1
情况2必须满足
1.0<=i<j
2. a[j]>a[i]

第三步:计算顺序
计算 f[0],f[1],…,f[n-1]
答案就是这些数中最大的那个

代码实现

class Solution:
    def lengthOfLIS(self, nums: List[int]) -> int:
        # 动态规划
        arr = [1] * len(nums)
        for i in range(1, len(nums)):
            for j in range(i):
                if nums[i] > nums[j]:
                    arr[i] = max(arr[j] + 1, arr[i])
        return max(arr)
class Solution:
    def lengthOfLIS(self, nums: List[int]) -> int:
        # 动态规划
        dp = []
        for i in range(len(nums)):
            dp.append(1)
            for j in range(i):
                if nums[i] > nums[j]:
                    dp[i] = max(dp[j] + 1, dp[i])
        return max(dp)

4. 最少完全平方数

LeetCode279
https://leetcode.cn/problems/perfect-squares/description/

思路分析

手动画一下
在这里插入图片描述

使用DP来实现

第一步:确定状态和子问题
状态:f[i] i最少被分成几个完全平方数之和
子问题:参考硬币的问题,f[i] = min(f[i-j*j]+1, f[i]) 1<=j<i^0.5

第二步:状态转移方程
f[i] = min(f[i-j*j]+1, f[i]) 1<=j<i^0.5

第三步:初始和边界条件
f[0] = 0

第四步:计算顺序
计算 f[0],f[1],…,f[n-1],f[n]
答案就是f[n]

代码实现


class Solution:
    def numSquares(self, n: int) -> int:
        dp = [0]
        for i in range(1, n + 1):
            dp.append(i)
            for j in range(1, int(i**0.5) +1):
                dp[i] = (min(dp[i-j**2]+1, dp[i] ))
        return dp[n]

5. 再论青蛙跳

LeetCode 55
https://leetcode.cn/problems/jump-game/description/

思路分析
典型的贪心问题,下面从动态规划的角度来分析解题

  1. 状态和子问题
    状态:f[x] 能否跳跃值x
    子问题:可以跳到j,j可以跳到i
  2. 状态转移方程
    f[i] = True | 0<=j<i and f[j] and a[j]>=i-j
  3. 初始和边界条件
    f[0] = True
  4. 顺序
    计算 f[0],f[1],…,f[n-1] 答案就是f[n-1]

代码实现

class Solution:
    def canJump(self, nums: List[int]) -> bool:
        # 动态规划
        bp = [False] * len(nums)
        bp[0] = True
        for i in range(1, len(nums)):
            for j in range(i):
                if bp[j] and nums[j] >= i - j:
                    bp[i] = True
        return bp[-1]

注:动态规划可以实现,但在LeetCode上,运行超出时间限制

6. 解码问题

LeetCode 91
https://leetcode.cn/problems/decode-ways/description/

思路分析

  1. 状态和子问题
    状态:f[i] 以a[i]结尾,可以有多少种解码方式
    子问题:
    最后一个字母的解码有两种情况
    情况1:1个数字解码 a[i]对应一个字母,f[i] = f[i-1]
    情况2:2个数字解码 a[i-1]a[i]对应一个字母,f[i] = f[i-2]

    综上,f[i] = f[i-1](条件:a[i]可以对应一个字母) + f[i-2](条件:a[i-1]a[i]可以对应一个字母)

  2. 状态转移方程
    f[i] = f[i-1](条件:a[i]可以对应一个字母) + f[i-2](条件:a[i-1]a[i]可以对应一个字母)

  3. 初始和边界条件
    初始条件f[0] = 1 理解为空串,有一种解码方式
    边界条件:i = 1,只看最后一个数字就行了

  4. 顺序
    计算 f[0],f[1],…,f[n-1] 答案就是f[n]

代码实现

class Solution:
    def numDecodings(self, s: str) -> int:
        n = len(s)
        dp = [0] * (n + 1)
        dp[0] = 1
        for i in range(1, n + 1):
            if s[i - 1] != '0':
                dp[i] += dp[i - 1]
            if i > 1 and 10 <= int(s[i - 2]) * 10 + int(s[i - 1]) <= 26:
                dp[i] += dp[i - 2]
        return dp[len(s)]

7. 路径中存在障碍物

LeetCode 63
https://leetcode.cn/problems/unique-paths-ii/description/

我们在路径部分介绍了多种路径的问题
本专题有个重要的拓展,加入网格中存在障碍物怎么办?

本题是在 LeetCode 62 的基础上,如果中间某个位置存在障碍物,那一共有多少种路径。

示例
输入    obstacleGrid = [[0,0,0], [0,1,0], [0,0,0]]
输出    2
解释    3x3 网格的正中间有一个障碍物
        从左上角到右下角一共有2条不同的路径
        1. 向右->向右->向下->向下
        2. 向下->向下->向右->向右

在这里插入图片描述

思路分析

处理方法不算复杂
设置没有障碍物的格子标记为0,有障碍物的格子标记为1
执行的时候如果当前位置dp[i][j] == 1时,直接跳过

代码实现

class Solution:
    def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
        m = len(obstacleGrid)
        n = len(obstacleGrid[0])
        bp = [[0] * n for _ in range(m)]
        bp[0][0] = 1 if obstacleGrid[0][0] == 0 else 0
        for i in range(m):
            for j in range(n):
                if obstacleGrid[i][j] == 1:
                    bp[i][j] = 0
                elif i >= 1 and j >= 1:
                    bp[i][j] = bp[i - 1][j] + bp[i][j - 1]
                elif i >= 1:
                    bp[i][j] = bp[i - 1][j]
                elif j >= 1:
                    bp[i][j] = bp[i][j - 1]
        return bp[-1][-1]
class Solution:
    def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
        # 滚动数组实现
        m = len(obstacleGrid)
        n = len(obstacleGrid[0])
        dp = [0] * n
        dp[0] = 1 if obstacleGrid[0][0] == 0 else 0
        for i in range(m):
            for j in range(n):
                if obstacleGrid[i][j] == 1:
                    dp[j] = 0
                elif j - 1 >= 0 and obstacleGrid[i][j - 1] == 0:
                    dp[j] += dp[j - 1]
        return dp[n - 1]

8. 滚动数组技巧

LeetCode 118
https://leetcode.cn/problems/pascals-triangle/description/
LeetCode 119
https://leetcode.cn/problems/pascals-triangle-ii/description/

杨辉三角
特点:每个元素嗾使其二维矩阵中左上方和右上方的元素之和,是一种对称结构
在这里插入图片描述

用二维数组表示
在这里插入图片描述

  • 每一行的最右侧和最左侧都是1
  • 前两行时1,第3行才开始有累加的问题
  • 每一行的元素数量与其行数一样

代码实现

LeetCode 119

class Solution:
    def getRow(self, rowIndex: int) -> List[int]:
        # 新建二维数组
        a = [[] for _ in range(rowIndex+1)]

        for i in range(rowIndex+1):
            # 确定每一行数组
            a[i] = [0] * (i + 1)
            # 第1个和最后1个元素为1
            a[i][0] = 1
            a[i][i] = 1

        for i in range(rowIndex+1):
            # 从第3行开始
            if i >= 2:
                for j in range(1, len(a[i]) - 1):
                    a[i][j] = a[i - 1][j - 1] + a[i - 1][j]

        return a[-1]

思路分析

如果要求只能使用O(n)空间实现呢?可以使用上面提到的滚动数组来做

a[i][j] = a[i-1][j-1] + a[i-1][j]

存在问题:计算dp[i]的时候,需要上一轮的dp[i-1],但是这个值已经被覆盖了
例如下图中的 3 需要使用上一轮的2和1进行相加,但是此时2已经覆盖成3了,所以仅靠一个一维数组无法解决问题

在这里插入图片描述

可以使用两个数组,也是O(n)空间,使用两个数组来进行轮换交流
如下图所示,黑色代表上一轮的结构,红色表示当前轮更新的结果
在这里插入图片描述

代码实现

LeetCode 119

class Solution:
    def getRow(self, rowIndex: int) -> List[int]:
        # 滚动数组,两个一维数组
        pre = []
        cur = []
        for i in range(rowIndex+1):
            for j in range(i + 1):
                if j == 0 or i == j:
                    cur.append(1)
                else:
                    cur.append(pre[j - 1] + pre[j])
            pre = cur
            cur = []
        return pre

思路分析

如果只能使用一个一维数组来完成,该怎么做呢?

观察 cur[j] = pre[j-1] + pre[j],第 j 项的计算与上一行第 j-1 项和第 j 项有关

可以倒着算,就没有影响了,先计算第 j 项,再计算第 j-1 项,这样计算第 j 项时,第 j-1 项还是上一行的值
cur[j] = cur[j-1] + cur[j]

# 两个二维数组
for j in range(i + 1):
    if j == 0 or i == j:
        cur.append(1)
    else:
        cur.append(pre[j - 1] + pre[j])

变为

# 一个二维数组
for j in range(i, -1, -1):
    if j == 0 or i == j:
        arr[j] = 1
    else:
        arr[j] = arr[j - 1] + arr[j]

代码实现

LeetCode 119

class Solution:
    def getRow(self, rowIndex: int) -> List[int]:
        # 滚动数组,一个一维数组
        arr = []
        for i in range(rowIndex+1):
            arr.append(0)
            for j in range(i, -1, -1):
                if j == 0 or i == j:
                    arr[j] = 1
                else:
                    arr[j] = arr[j - 1] + arr[j]
        return arr

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1008549.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深入理解JVM虚拟机第六篇:内存结构与类加载子系统概述

文章目录 一&#xff1a;内存结构概述 1&#xff1a;运行时数据区 2&#xff1a;运行时数据区简图 3&#xff1a;运行时数据区详细图中英文版 二&#xff1a;类加载器子系统 1&#xff1a;加载 2&#xff1a;连接 3&#xff1a;初始化 一&#xff1a;内存结构概述 1…

CAN基础概念

文章目录 目的控制器、收发器、总线帧格式CAN2.0和CAN-FD波特率与采样点工作模式总结 目的 CAN是非常常用的一种数据总线&#xff0c;被广泛用在各种车辆系统中。大多数时候CAN的控制器和收发器干了比较多的工作&#xff0c;从而对于写代码使用来说比较简单。这篇文章将对CAN使…

经历网数据库共享

经历网&#xff0c;为留住您的经历而生 点击 经历网 进入网站查看当前数据 经历网网址&#xff1a;https://www.jili20.com/ 以下 数据库 数据 截止至 2023年9月13日 1&#xff09;百度网盘 提取 链接&#xff1a;https://pan.baidu.com/s/1WwR4cI9lbSAYTuffo8qmVQ 或点击 此…

微信小程序的在线课外阅读打卡记录系统uniapp

本文从管理员、学生和教师的功能要求出发&#xff0c;中学课外阅读记录系统中的功能模块主要是实现学生、教师、阅读任务、阅读打卡、提醒信息、阅读排行、任务计划、阅读类型、在线考试等。经过认真细致的研究&#xff0c;精心准备和规划&#xff0c;最后测试成功&#xff0c;…

zemax畸变与消畸变

物体不同位置的放大率不同&#xff0c;产生图形变形 这里选择zemax自带的案例&#xff1a; 畸变效果&#xff1a; 明显的负畸变&#xff08;桶形畸变&#xff09; 从场曲畸变图中可以看出&#xff1a; 该系统的最大畸变大约为38% 放入图片观察成像效果&#xff1a; 优化操作数…

GpsAndMap模块开源,欢迎测评

背景 之前的文章有提到&#xff0c;最近在使用folium的过程中&#xff0c;深感对于一个非专业人员来说&#xff0c;GPS坐标以及其所隐含的GPS坐标系&#xff0c;以及不同GPS坐标系之间的相互转换关系&#xff0c;不是一个十分清晰的概念&#xff0c;往往造成在使用GPS坐标在fo…

基本的SELECT语句——“MySQL数据库”

各位CSDN的uu们好呀&#xff0c;好久没有更新小雅兰的MySQL数据库专栏啦&#xff0c;接下来一段时间&#xff0c;小雅兰都会更新MySQL数据库的知识&#xff0c;下面&#xff0c;让我们进入今天的主题吧——基本的SELECT语句&#xff01;&#xff01;&#xff01; SQL概述 SQL语…

Linux - 性能可观察性工具

文章目录 常用的Linux性能可观察性工具图解小结 常用的Linux性能可观察性工具 以下是一些常用的Linux性能可观察性工具&#xff1a; top: 显示实时的系统性能数据&#xff0c;包括CPU使用率、内存使用情况、进程信息等。 htop: 类似于top&#xff0c;但提供了更多的交互式功能…

谷粒商城----rabbitmq

一、 为什么要用 MQ? 三大好处&#xff0c;削峰&#xff0c;解耦&#xff0c;异步。 削峰 比如秒杀&#xff0c;或者高铁抢票&#xff0c;请求在某些时间点实在是太多了&#xff0c;服务器处理不过来&#xff0c;可以把请求放到 MQ 里面缓冲一下&#xff0c;把一秒内收到的…

Arcgis栅格转点时ERROR 999999: 执行函数时出错。 无法创建要素数据集。 执行(RasterToPoint)失败

Arcgis栅格转点时ERROR 999999: 执行函数时出错。 无法创建要素数据集。 执行(RasterToPoint)失败。 问题描述 原因 输出点要素的位置不对 解决方案 点击新建文件地理数据库 然后在该文件地理数据库下输出

RocketMQ 消息传递模型

文章目录 0. 前言1. RocketMQ的消息传递模型1.1. 同步发送1.2. 异步发送1.3. 单向发送 2. RocketMQ的批量发送和消费2.1 批量发送2.2 批量消费2.3 Spring Boot集成RocketMQ官方starter 示例 3. 总结4. 参考文档5. 源码地址 0. 前言 RocketMQ 支持6种消息传递方式&#xff0c;我…

【Java 基础篇】Java 泛型:类型安全的编程指南

在 Java 编程中&#xff0c;泛型是一项强大的特性&#xff0c;它允许您编写更通用、更安全和更灵活的代码。无论您是初学者还是有经验的 Java 开发人员&#xff0c;了解和掌握泛型都是非常重要的。本篇博客将从基础概念一直深入到高级应用&#xff0c;详细介绍 Java 泛型。 什…

nrf52832蓝牙GAP 通用访问规范

nrf52832蓝牙GAP 通用访问规范 文章目录 nrf52832蓝牙GAP 通用访问规范前言一、蓝牙GAP&#xff08;通用访问配置文件&#xff09;可以设置什么参数&#xff1f;二、使用步骤广播名称修改广播名字长度&#xff1b;全显示和自定义显示中文显示广播名称 蓝牙图标没有图标加入图标…

ArmSom-W3开发板之PCIE的开发指南(一)

1. 简介 RK3588从入门到精通本⽂介绍RK平台配置pcie的方法开发板&#xff1a;ArmSoM-W3 2、PCIE接口概述 PCIe&#xff08;Peripheral Component Interconnect Express&#xff09;是一种用于连接计算机内部组件的高速接口标准。以下是关于PCIe接口的简要介绍&#xff1a; …

【计算机网络】 TCP流量控制——滑动窗口和累积应答

文章目录 累积应答TCP流量控制——滑动窗口 累积应答 我们前面所说的是我们每发送一个包对端就要回一个ack&#xff0c;那么这样效率太慢了&#xff0c;我们这里就有一个累积应答的机制&#xff0c;就是说我们客户端累积发送多个包&#xff0c;然后服务端再统一进行回复。 TCP…

被“多元平等共融”种草——2023谷歌开发者大会参会体验

谷歌开发者大会又称Google I/O Connect&#xff0c;是谷歌公司每年一次举办的开发者年会&#xff0c;谷歌中国的开发者大会按照惯例是在每年9月份的上海世博中心举办&#xff0c;为期两天。这两天中&#xff0c;通过主旨大会和多场连续专题演讲以及现场演示向参会人员展示谷歌产…

【Teams】Teams的组织名称变更

最近在使用Teams的过程中&#xff0c;发现有些企业创建组织的过程中创建了默认的组织&#xff1a;MSFT。如果创建组织的过程中没有修改组织名称&#xff0c;我们就会发现默认的组织名称就是MSFT。如果多个企业没有更改MSFT则可能在切换Teams账户的时候可能不知道目前Teams切换的…

Jetpack Compose基础组件之 — Text

Text的源码参数预览 Composable fun Text(text: String,modifier: Modifier Modifier,color: Color Color.Unspecified,fontSize: TextUnit TextUnit.Unspecified,fontStyle: FontStyle? null,fontWeight: FontWeight? null,fontFamily: FontFamily? null,letterSpac…

YOLO物体检测-系列教程1:YOLOV1整体解读(预选框/置信度/分类任/回归任务/损失函数/公式解析/置信度/非极大值抑制)

&#x1f388;&#x1f388;&#x1f388;YOLO 系列教程 总目录 YOLOV1整体解读 YOLOV2整体解读 YOLOV1提出论文&#xff1a;You Only Look Once: Unified, Real-Time Object Detection 1、物体检测经典方法 two-stage&#xff08;两阶段&#xff09;&#xff1a;Faster-rc…

PMP-项目启动过程组的重要性

一、什么是项目启动过程组 启动过程组包括定义一个新项目或现有项目的一个新阶段&#xff0c;授权开始该项目或阶段的一组过程。启动过程组的目的是&#xff1a;协调相关方期望与项目目的&#xff0c;告知相关方项目范围和目标&#xff0c;并商讨他们对项目及相关阶段的参与将如…