【算法专题】动态规划之斐波那契数列模型
动态规划1.0
- 动态规划 - - - 斐波那契数列模型
- 1. 第 N 个泰波那契数
- 2. 三步问题
- 3. 使用最小花费爬楼梯
- 4. 解码方法
动态规划 - - - 斐波那契数列模型
1. 第 N 个泰波那契数
题目链接 -> Leetcode -1137. 第 N 个泰波那契数
Leetcode -1137. 第 N 个泰波那契数
题目:泰波那契序列 Tn 定义如下:
T0 = 0, T1 = 1, T2 = 1, 且在 n >= 0 的条件下 Tn + 3 = Tn + Tn + 1 + Tn + 2
给你整数 n,请返回第 n 个泰波那契数 Tn 的值。
示例 1:
输入:n = 4
输出:4
解释:
T_3 = 0 + 1 + 1 = 2
T_4 = 1 + 1 + 2 = 4
示例 2:
输入:n = 25
输出:1389537
提示:
0 <= n <= 37
答案保证是一个 32 位整数,即 answer <= 2 ^ 31 - 1。
思路:
- 状态表示:这道题可以「根据题目的要求」直接定义出状态表示:dp[i] 表示:第 i 个泰波那契数的值。
- 状态转移方程:dp[i] = dp[i - 1] + dp[i - 2] + dp[i - 3]
- 初始化:从我们的递推公式可以看出, dp[i] 在 i = 0 以及 i = 1 的时候是没有办法进行推导的,因为 dp[-2] 或 dp[-1] 不是一个有效的数据。因此我们需要在填表之前,将 0, 1, 2 位置的值初始化。题目中已经告诉我们 dp[0] = 0, dp[1] = dp[2] = 1 。
- 填表顺序:从左往右
- 返回值:应该返回 dp[n] 的值。
代码如下:
class Solution {public:int tribonacci(int n){if (n == 0 || n == 1) return n;// 动态规划,当前位置的值等于前三个位置的值相加vector<int> dp(n + 1);dp[1] = dp[2] = 1; // 先初始化前面的位置// 开始使用动态规划for (int i = 3; i <= n; i++)dp[i] = dp[i - 1] + dp[i - 2] + dp[i - 3];return dp[n];}};
2. 三步问题
题目链接 -> Leetcode -面试题 08.01.三步问题
Leetcode -面试题 08.01.三步问题
题目:三步问题。有个小孩正在上楼梯,楼梯有n阶台阶,小孩一次可以上1阶、2阶或3阶。
实现一种方法,计算小孩有多少种上楼梯的方式。结果可能很大,你需要对结果模1000000007。
示例1 :
输入:n = 3
输出:4
说明 : 有四种走法
示例2 :
输入:n = 5
输出:13
提示 :
- n范围在[1, 1000000]之间
思路:
-
状态表示:dp[i] 表示:到达 i 位置时,一共有多少种方法。
-
状态转移方程:
以 i 位置状态的最近的⼀步,来分情况讨论:
如果 dp[i] 表示小孩上第 i 阶楼梯的所有方式,那么它应该等于所有上一步的方式之和:
i. 上一步上一级台阶, dp[i] += dp[i - 1] ;
ii. 上一步上两级台阶, dp[i] += dp[i - 2] ;
iii. 上一步上三级台阶, dp[i] += dp[i - 3] ;
综上所述, dp[i] = dp[i - 1] + dp[i - 2] + dp[i - 3] -
初始化从我们的递推公式可以看出, dp[i] 在 i = 0, i = 1 以及 i = 2 的时候是没有办法进行推导的,因为 dp[-3] dp[-2] 或 dp[-1] 不是⼀个有效的数据。因此我们需要在填表之前,将 1, 2, 3 位置的值初始化。根据题意, dp[1] = 1, dp[2] = 2, dp[3] = 4 。
-
填表顺序:从左往右
-
返回值:应该返回 dp[n] 的值。
代码如下:
class Solution {public:int waysToStep(int n){if (n == 1 || n == 2) return n;vector<int> dp(n + 1);dp[1] = 1, dp[2] = 2, dp[3] = 4; // 初始化// 走到当前台阶的方法数等于,到达前三个台阶的方法数相加;// 因为前三个台阶走一步,走两步,走三步都可以到达当前台阶,加上这一步、两步或三步,都是同一种方法for (int i = 4; i <= n; i++)dp[i] = ((dp[i - 1] + dp[i - 2]) % 1000000007 + dp[i - 3]) % 1000000007;return dp[n];}};
3. 使用最小花费爬楼梯
题目链接 -> Leetcode -746.使用最小花费爬楼梯
Leetcode -746.使用最小花费爬楼梯
题目:给你一个整数数组 cost ,其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦你支付此费用,即可选择向上爬一个或者两个台阶。
你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。
请你计算并返回达到楼梯顶部的最低花费。
示例 1:
输入:cost = [10, 15, 20]
输出:15
解释:你将从下标为 1 的台阶开始。
- 支付 15 ,向上爬两个台阶,到达楼梯顶部。
总花费为 15 。
示例 2:
输入:cost = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1]
输出:6
解释:你将从下标为 0 的台阶开始。
- 支付 1 ,向上爬两个台阶,到达下标为 2 的台阶。
- 支付 1 ,向上爬两个台阶,到达下标为 4 的台阶。
- 支付 1 ,向上爬两个台阶,到达下标为 6 的台阶。
- 支付 1 ,向上爬一个台阶,到达下标为 7 的台阶。
- 支付 1 ,向上爬两个台阶,到达下标为 9 的台阶。
- 支付 1 ,向上爬一个台阶,到达楼梯顶部。
- 总花费为 6 。
提示:
- 2 <= cost.length <= 1000
- 0 <= cost[i] <= 999
思路:
- 状态表示:dp[i] 表示:到达 i 位置时的最小花费。(注意:到达 i 位置的时候,i 位置的钱不需要算上)
- 状态转移方程:根据最近的一步,分情况讨论:
- 先到达 i - 1 的位置,然后支付 cost[i - 1] ,接下来走一步走到 i 位置:dp[i - 1] + csot[i - 1] ;
- 先到达 i - 2 的位置,然后⽀付 cost[i - 2] ,接下来走一步走到 i 位置:dp[i - 2] + csot[i - 2] 。
- 初始化:从我们的递推公式可以看出,我们需要先初始化 i = 0 ,以及 i = 1 位置的值。容易得到 dp[0] = dp[1] = 0 ,因为不需要任何花费,就可以直接站在第 0 层和第 1 层上。
- 填表顺序:根据「状态转移方程」可得,遍历的顺序是「从左往右」。
- 返回值:根据「状态表示以及题目要求」,需要返回 dp[n] 位置的值。
代码如下:
class Solution {public:int minCostClimbingStairs(vector<int>& cost){int n = cost.size();// 从第三个阶梯开始,当前阶梯往上爬的费用等于前两个费用的较小值加上爬当前阶梯需要的费用for (int i = 2; i < n; i++)cost[i] = min(cost[i - 1], cost[i - 2]) + cost[i];// 最后返回最后倒数第一个和第二个阶梯的最小值return min(cost[n - 1], cost[n - 2]);}};
4. 解码方法
题目链接 -> Leetcode -91.解码方法
Leetcode -91.解码方法
题目:一条包含字母 A - Z 的消息通过以下映射进行了 编码 :
‘A’ -> “1”
‘B’ -> “2”
…
‘Z’ -> “26”
要解码已编码的消息,所有数字必须基于上述映射的方法,反向映射回字母(可能有多种方法)。例如,“11106” 可以映射为:
“AAJF” ,将消息分组为(1 1 10 6)
“KJF” ,将消息分组为(11 10 6)
注意,消息不能分组为(1 11 06) ,因为 “06” 不能映射为 “F” ,这是由于 “6” 和 “06” 在映射中并不等价。
给你一个只含数字的 非空 字符串 s ,请计算并返回 解码 方法的 总数 。
题目数据保证答案肯定是一个 32 位 的整数。
示例 1:
输入:s = “12”
输出:2
解释:它可以解码为 “AB”(1 2)或者 “L”(12)。
示例 2:
输入:s = “226”
输出:3
解释:它可以解码为 “BZ” (2 26), “VF” (22 6), 或者 “BBF” (2 2 6) 。
示例 3:
输入:s = “06”
输出:0
解释:“06” 无法映射到 “F” ,因为存在前导零(“6” 和 “06” 并不等价)。
提示:
- 1 <= s.length <= 100
- s 只包含数字,并且可能包含前导零。
思路:
- 状态表示:根据上题的经验,对于大多数线性 dp ,我们经验上都是「以某个位置结束或者开始」做文章,这里我们继续尝试「用 i 位置为结尾」结合「题目要求」来定义状态表示。
dp[i] 表示:字符串中 [0,i] 区间上,一共有多少种编码方法 - 状态转移方程:定义好状态表示,我们就可以分析 i 位置的 dp 值,关于 i 位置的编码状况,我们可以分为下面两种情况:
i. 让 i 位置上的数单独解码成⼀个字母;
ii. 让 i 位置上的数与 i - 1 位置上的数结合,解码成一个字母。
下面我们就上面的两种解码情况,继续分析:
- 让 i 位置上的数单独解码成一个字母,就存在「解码成功」和「解码失败」两种情况:
i. 解码成功:当 i 位置上的数在 [1, 9] 之间的时候,说明 i 位置上的数是可以单独解码的,那么此时 [0, i] 区间上的解码方法应该等于 [0, i - 1] 区间上的解码方法。因为 [0, i - 1] 区间上的所有解码结果,后面填上⼀个 i 位置解码后的字母就可以了。此时 dp[i] = dp[i - 1] ;
ii. 解码失败:当 i 位置上的数是 0 的时候,说明 i 位置上的数是不能单独解码的,那么此时 [0, i] 区间上不存在解码方法。因为 i 位置如果单独参与解码,但是解码失败了,那么前面做的就全部白费了。此时 dp[i] = 0 。 - 让 i 位置上的数与 i - 1 位置上的数结合在⼀起,解码成一个字母,也存在「解码成功」和「解码失败」两种情况:
i. 解码成功:当结合的数在 [10, 26] 之间的时候,说明 [i - 1, i] 两个位置是可以解码成功的,那么此时 [0, i] 区间上的解码方法应该等于 [0, i - 2 ] 区间上的解码方法,原因同上。此时 dp[i] = dp[i - 2] ;
ii. 解码失败:当结合的数在 [0, 9] 和 [27 , 99] 之间的时候,说明两个位置结合后解码失败(这里⼀定要注意 00 01 02 03 04 … 这几种情况),那么此时 [0, i] 区间上的解码方法就不存在了,原因依旧同上。此时 dp[i] = 0 。
综上所述: dp[i] 最终的结果应该是上面四种情况下,解码成功的两种的累加和(因为我们关心的是解码方法,既然解码失败,就不用加入到最终结果中去),因此可以得到状态转移方程( dp[i] 默认初始化为 0 ):
- 当 s[i] 上的数在 [1, 9] 区间上时: dp[i] += dp[i - 1] ;
- 当 s[i - 1] 与 s[i] 上的数结合后,在 [10, 26] 之间的时候: dp[i] += dp[i - 2] ;
如果上述两个判断都不成立,说明没有解码方法, dp[i] 就是默认值 0 .
-
初始化:可以在最前面加上一个辅助结点,帮助我们初始化。使用这种技巧要注意两个点:
i. 辅助结点里面的值要保证后续填表是正确的;
ii. 下标的映射关系 -
填表顺序:「从左往右」
-
返回值:应该返回 dp[n - 1] 的值,表示在 [0, n - 1] 区间上的编码方法。
代码如下:
class Solution {public:int numDecodings(string s){int n = s.size();// 创建一个 dp 表,多开一个空间,即添加辅助位置初始化vector<int> dp(n + 1);dp[0] = 1; // 因为前面的初始化会影响后面的填表,所以此处应该初始化为1// 只要第一个字符不是 0,那么当前位置的解码数就是1if (s[0] != '0') dp[1] = 1;// 开始填表for (int i = 2; i <= n; i++){// 单独自己一个数编码(dp表的下标与原字符串的下标偏移量为1,因为dp表多开了一个空间)if (s[i - 1] >= '1' && s[i - 1] <= '9'){dp[i] += dp[i - 1];}// 和前一个数联合起来编码int tmp = (s[i - 2] - '0') * 10 + (s[i - 1] - '0');if (tmp >= 10 && tmp <= 26){dp[i] += dp[i - 2];}}return dp[n];}};
相关文章:
【算法专题】动态规划之斐波那契数列模型
动态规划1.0 动态规划 - - - 斐波那契数列模型1. 第 N 个泰波那契数2. 三步问题3. 使用最小花费爬楼梯4. 解码方法 动态规划 - - - 斐波那契数列模型 1. 第 N 个泰波那契数 题目链接 -> Leetcode -1137. 第 N 个泰波那契数 Leetcode -1137. 第 N 个泰波那契数 题目&…...
K2P路由器刷OpenWrt官方最新版本固件OpenWrt 23.05.2方法 其他型号的智能路由器OpenWrt固件刷入方法也基本上适用
最近路由器在开机时总出问题,于是就那他来开刀,直接刷一个OpenWrt官方最新版本的固件, 刷其他第三方的固件总是觉得不安全, 而且很多第三方固件都带了些小工具,始终会有安全隐患, 而且占用内存空间太多,本来这个东西就没有多少内存,于是就干脆刷一个官方的原始固件(才6.3M, 相…...
AI大语言模型会带来了新一波人工智能浪潮?
以ChatGPT、LLaMA、Gemini、DALLE、Midjourney、Stable Diffusion、星火大模型、文心一言、千问为代表AI大语言模型带来了新一波人工智能浪潮,可以面向科研选题、思维导图、数据清洗、统计分析、高级编程、代码调试、算法学习、论文检索、写作、翻译、润色、文献辅助…...
How to view the high-tech zone atmospheric project
How to view the high-tech zone atmospheric project 问题与建议登录界面没有验证码部分页面加载时间过长联动型下拉列表框点击反应迟钝页面缺乏导航没有采用https协议没有完成域名实名认证左侧菜单区不能收缩大屏区域功能图层不能完全隐藏部分页面表单控件没有文案提示其功能…...
sqlalchemy 中的缓存机制解释
SQLAlchemy 的缓存机制主要涉及两个层面:会话(Session)缓存和查询缓存。这两种缓存机制对于提升应用性能和数据一致性都非常重要。下面详细解释这两种缓存机制: 1. 会话(Session)缓存 会话缓存是 SQLAlch…...
网络安全B模块(笔记详解)- 漏洞扫描与利用
漏洞扫描与利用 1.通过Kali对服务器场景server2003以半开放式不进行ping的扫描方式并配合a,要求扫描信息输出格式为xml文件格式,从生成扫描结果获取局域网(例如172.16.101.0/24)中存活靶机,以xml格式向指定文件输出信息(使用工具Nmap,使用必须要使用的参数),并将该操…...
【C语言】指针——从底层原理到应用
C语言指针-从底层原理到花式技巧,用图文和代码帮你讲解透彻 目录 一、前言二、变量与指针的本质 1. 内存地址2. 32位与64位系统3. 变量4. 指针变量5. 操作指针变量 5.1 指针变量自身的值5.2 获取指针变量所指向的数据5.3 以什么样的数据类型来使用/解释指针变量所指…...
想了解步进伺服的朋友可以了解下这个方案
TMC4361A 是一款小型化、高性能的驱动步进电机的运动控制器。实用于很多的斜坡轮廓的应用,特别是速度快、限制过冲的运动场合。用户根据自己的要求实现 S 形或 sixPoint™六点式速度轮廓配置及闭环或开环的操作、动态修改运动参数。TMC4361A 包含 SPI接口、Step/Dir…...
航天航空线束工艺3D虚拟展馆支持多人异地参观漫游
为了满足汽车线束企业员工工作需要,让新老员工了解到更先进、规范的线束工艺设计技术,华锐视点基于VR虚拟仿真、web3d开发和图形图像技术制作了一款汽车线束工艺设计VR虚拟仿真模拟展示系统。 汽车线束工艺设计VR虚拟仿真模拟展示系统共分为pc电脑端和VR…...
JAVA面向对象基础-容器
一、泛型 我们可以在类的声明处增加泛型列表,如:<T,E,V>。 此处,字符可以是任何标识符,一般采用这3个字母。 【示例9-1】泛型类的声明 1 2 3 4 5 6 7 8 9 10 class MyCollection<E> {// E:表示泛型; Object[] o…...
2022年山东省职业院校技能大赛高职组信息安全管理与评估—开发测试服务器解析
任务5:开发测试服务器 目录 任务5:开发测试服务器 解题方法:...
2024年我国网络安全发展形势展望
2023年,我国网络安全政策法规陆续出台,网络安全与数据安全产业发展势头强劲,网络安全形势整体向好。展望2024年,世界各国在网络空间中的竞争将变得愈发激烈,我国网络安全领域的法律法规将不断完善,数据安全…...
如何使用 NFTScan NFT API 在 PlatON 网络上开发 Web3 应用
PlatON 是由万向区块链和矩阵元主导开发的面向下一代的全球计算架构,创新性的采用元计算框架 Monad 和基于 Reload 覆盖网络的同构多链架构,其愿景是成为全球首个提供完备隐私保护能力的运营服务网络。它提供计算、存储、通讯服务,并提供算力…...
如何使用web文件管理器Net2FTP搭建个人网盘
文章目录 1.前言2. Net2FTP网站搭建2.1. Net2FTP下载和安装2.2. Net2FTP网页测试 3. cpolar内网穿透3.1.Cpolar云端设置3.2.Cpolar本地设置 4.公网访问测试5.结语 1.前言 文件传输可以说是互联网最主要的应用之一,特别是智能设备的大面积使用,无论是个人…...
总结多线程的各种锁
1、公平锁和非公平锁 公平锁是严格按照线程请求的顺序来分配锁,每一个线程都能获取到锁,避免线程饥饿现象;相反,非公平锁表示线程竞争锁时可以插队来抢占资源。 非公平锁在大多数情况下效率优于公平锁,因为公平锁涉及到…...
树形结构的窗口小部件
这段代码是一个使用Qt框架的C程序,实现了一个树形结构的窗口小部件(TreeWidget)。以下是主要的解释: #include "treewidget.h" #include "ui_treewidget.h"TreeWidget::TreeWidget(QWidget *parent) : QWidg…...
【现代密码学】笔记3.1-3.3 --规约证明、伪随机性《introduction to modern cryphtography》
【现代密码学】笔记3.1-3.3 --规约证明、伪随机性《introduction to modern cryphtography》 写在最前面私钥加密与伪随机性 第一部分密码学的计算方法论计算安全加密的定义:对称加密算法 伪随机性伪随机生成器(PRG) 规约法规约证明 构造安全…...
Redis底层原理
持久化 Redis虽然是个内存数据库,但是Redis支持RDB和AOF两种持久化机制,将数据写往磁盘,可以有效地避免因进程退出造成的数据丢失问题,当下次重启时利用之前持久化的文件即可实现数据恢复。 RDB RDB持久化是把当前进程数据生成快照保存到硬盘的过程。所谓内存快照,就是…...
掌握亚马逊、Lazada、shopee、速卖通、eBay、wish测评自养号补单系统:解锁跨境电商新机遇
在选择测评环境系统时,市面上有很多选项。但是,究竟哪个系统使用起来更高效、成本更低、成功率更高呢?下面将详细分析各种网络环境的使用经验,希望能帮助大家避免一些不必要的困扰和错误。我曾经亲自尝试过各种网络环境࿰…...
15_多线程
文章目录 OS中的基本概念进程(process)与线程(thread)串行(serial)、并行(parallel)与并发(concurrency)同步(synchronization)与异步(asynchronization) java程序运行原理java命令主类类名运行原理 多线程的实现方式一࿱…...
吉他打谱软件Guitar Pro8苹果Mac电脑简体中文特别版
Guitar Pro 8 Mac是一款吉他编曲学习软件,用于吉他、贝和其他弦乐器的制谱和演奏,这是一个多轨编辑器,具有集成的 MIDI 编辑器、合唱绘图仪、吉他、节拍器和其他音乐家工具。它使您能够编辑吉他、贝司和尤克里里、乐谱、指法谱,并…...
go study oneday
这段代码的详细解释,涵盖了Go 语言变量声明、函数调用、用户输入、类型转换以及结果输出。 package main import "fmt" func main() {var num1 intvar num2 float32var num3 intfmt.Println("请输入数字一:")fmt.Scanln(&num1)f…...
Avatar虚拟数字人方案,元宇宙时代的企业新动力
随着元宇宙概念的兴起,虚拟数字人技术逐渐成为各行业关注的焦点。为了满足市场需求,美摄科技凭借专业、自研的虚拟数字人技术,结合强大的ChatGPT能力,隆重推出Avatar虚拟数字人方案,助力企业实现营销及内容创作的生产力…...
用golang 实现给图片添加文字水印
package mainimport ("fmt""github.com/golang/freetype""image""image/draw""image/jpeg""io""os""time" )func main() {// 打开原始图片file, err : os.Open("004.jpeg")if err …...
苹果电脑Markdown文本编辑Typora mac功能介绍
Typora mac是一款跨平台的Markdown编辑器,支持Windows、MacOS和Linux操作系统。它具有实时预览功能,能够自动将Markdown文本转换为漂亮的排版效果,让用户专注于写作内容而不必关心格式调整。Typora Mac版除了支持常见的Markdown语法外&#x…...
大型语言模型与知识图谱的完美结合:从LLMs到RAG,探索知识图谱构建的全新篇章
最近,使用大型语言模型(LLMs)和知识图谱(KG)开发 RAG(Retrieval Augmented Generation)流程引起了很大的关注。在这篇文章中,我将使用 LlamaIndex 和 NebulaGraph 来构建一个关于费城费利斯队(Philadelphia Phillies)的 RAG 流程。 我们用的是开源的 NebulaGraph 来…...
Vue 缓存Hook:提高接口性能,减少重复请求
前言 在开发 Web 应用时,我们经常会遇到需要重复调用接口的场景。例如,当用户频繁刷新页面或进行某个操作时,我们可能需要多次请求相同的数据。这不仅会增加服务器负担,还会导致用户体验下降。为此,我们可以使用缓存机…...
【Python机器学习】用于回归的决策树
用于回归的决策树与用于分类的决策树类似,在DecisionTreeRegressor中实现。DecisionTreeRegressor不能外推,也不能在训练数据范围之外的数据进行预测。 利用计算机内存历史及格的数据进行实验,数据展示: import pandas as pd im…...
numpy库的一些常用函数
文章目录 广播(broadcast)迭代数组数组运算修改数组的形状 修改数组维度连接数组分割数组数组元素的添加与删除Numpy算术函数Numpy 统计函数Numpy排序、条件筛选函数条件筛选 import numpy as np anp.arange(15).reshape(3,5)aarray([[ 0, 1, 2, 3, …...
成员变量与局部变量的区别?
如果你现在需要准备面试,可以关注我的公众号:”Tom聊架构“,回复暗号:”578“,领取一份我整理的50W字面试宝典,可以帮助你提高80%的面试通过率,价值很高!! 语法形式&…...
南宁高端网站建设公司/东莞寮步最新通知
?点 Stephen 关 注 我 这是 Stephen 的第 76 篇原创文章哈喽,大家好,我是 Stephen,一个毕业三年后自学 Java 编程入行的程序员。我们知道松哥的 “微人事” 开源项目后面引入了 RabbitMQ 消息中间件。今天我们来一起学习 Windows 环境下 Ra…...
厦门疫情最新消息/seo培训
#!/bin/bash#####################################################Environment Setting####################################################### #程序代码数组APPS(shop euaker config) #程序名称数组 NAMES(店铺模块 euaker模块 config模块) #jar包JARS(message-pushmsg-…...
微信平台的微网站怎么做的/移动营销
本部分理解原理就好 Spring入门1 Spring引入1.1 原生web开发中存在的问题2 Spring2.1 Spring的概念2.2 Spring 作用2.3 Spring的组成2.4 spring的IOC底层实现原理3 Spring快速入门3.1 引入spring依赖3.2 spring的配置文件3.3 测试四、Spring的开发细节4.1 BeanFactory的类间关系…...
网站搭建服务/百度站长平台链接
云原生技术的不断普及,不仅让使用Kubernetes部署应用成为了当下最主流的方式,而且标志着众多企业迈入了多集群时代。随着集群数量的不断增长,企业在集群管理和运维方面也迎来了诸如集群配置重复劳动、维护管理繁琐等等问题和挑战。01 多集群生…...
网站后台模板 免费/网站优化的方式有哪些
公司的下午技术茶,听一些大咖谈何为敏捷,聚焦在下面几点敏捷宣言:个人与交互可用的软件客户协作响应变化个人感觉现在大家所谓的敏捷是一种理想状态,我们现有的瀑布模型、双V模型已加入了敏捷的概念,是敏捷思维和传统开…...
怎么在网站上做404页面/外链工厂
扩展教程 网站备案流程 转载于:https://www.cnblogs.com/Frank99/p/11028060.html...