Intro to Dynamic Programming 动态规划专题 [1]

1 动态规划简介

动态规划在查找有很多重叠子问题的情况的最优解时有效。它将问题重新组合成子问题。为了避免多次解决这些子问题,它们的结果都逐渐被计算并被保存,从简单的问题直到整个问题都被解决。因此,动态规划保存递归时的结果,因而不会在解决同样的问题时花费时间。

动态规划只能应用于有最优子结构的问题。最优子结构的意思是局部最优解能决定全局最优解(对有些问题这个要求并不能完全满足,故有时需要引入一定的近似)。简单地说,问题能够分解成子问题来解决。

2 动态规划题目特点

2.1 计数

  • 有多少种方式走到右下角(输出所有路径,用递归)
  • 有多少种方法选出K个数使得和为SUM

2.2 求最大最小值

  • 从左上角走到右下角路径的最大数字和
  • 最长上升子序列长度
  • 用最少的硬币组合付钱

2.3 求存在性

  • 取石子游戏,先后是否得胜
  • 能不能选出k个数使得和是Sum

例题:有数量不限,面值为[2, 5, 7] 的硬币,买27元的书,使用硬币一次付清不找零最少要几个硬币?

3 动态规划组成部分

3.1 确定状态

解动态规划的时候,需要开一个数组,数组的每个元素f[i] 或者 f[i][j] 代表什么,类似于解数学题中x, y, z 各代表什么。

确定状态需要两个意识:

  • 最后一步
    虽然目前并不知道最优策略,但最优策略肯定是K枚硬币a_1, a_2+…a_k = 27.

    所以一定有一枚最后的硬币: a_k.

    除掉最后这枚硬币,前面加起来是27- a_k
    在这里插入图片描述
    关键点一:
    我们并不关心前面k-1枚硬币怎么拼出27- a_k的,但可以确定前面的硬币拼出了27- a_k
    关键点二:
    因为是最优策略,所以拼出27-a_k 的硬币数一定要最少,否则就不是最优。

  • 子问题
    所以就先求,最少用多少枚硬币可以拼出27- a_k.
    如此便将原问题转化为了规模更小的子问题
    为简化定义,我们设状态f(X) = 最少用多少枚硬币拼出X.

目前还不知道a_k 是多少,但他只能是 2,5,7中的一个.

如果a_k 是2,f(27)应该是f(27-2) + 1
如果a_k是5,f(27)应该是f(27-5) + 1
如果a_k是7,f(27)应该是f(27-7) + 1

所以f(27) = Min{ f(27-2)+1, f(27-5)+1, f(27-7)+1 }

对比递归解法

int f(int X) {
	if(X==0)  return 0;
	int res = MAX_VALUE; 
	if(X>=2){
		res = Math.min(f(X-2)+1, res);
	}
	if(X>=5){
		res =Math.min(f(X-5)+1, res);
	}
	if(X>=7){
		res = Math.min(f(X-7)+1, res);
	}
	return res;
}
递归解法的问题:

在这里插入图片描述
可以看到,光 f(20) 就重复算了三次,而每算一次 f(20) 还要再算下面的。造成了运行时间的浪费。

如何避免重复计算,效率低下的问题?

动态规划:将计算结果保存下来,并改变计算顺序。

3.2 转移方程

因为动态规划一般需要开一个数组,接下来用 [ ] 来代替 ( )

设状态 f [X] = 最少用多少枚硬币拼出X.
对于任意X, f [X] = Min{ f [X-2]+1, f [X-5]+1, f [X-7]+1 }

3.3 写程序之前–初始条件和边界情况

对于转移方程 f [X] = Min{ f [X-2]+1, f [X-5]+1, f [X-7]+1 }, 有两个问题

  1. X-2, X-5, X-7小于零怎么办?
  2. 什么时候停下来?
  • 对于问题1, 如果不能拼出Y, 就定义f [Y] = 正无穷, 如 f [-1] = f [-2] = 正无穷. 这样的话, f [1] = MIn{ f [-1] +1, f [-4] +1, f[-6]+1 } = 正无穷,表示拼不出来 1

  • 初始条件 :f [0] = 0.
    初始条件就是用转移方程算不出来,但又需要补充的定义。

  • 边界条件: 不让数组越界

  • 计算顺序 ?:对这道题,从小到大算,这样可以避免重复计算,即当算f [X] 时,f [X-2],f [X-5], f [X-7] 都已经得到结果了。每一步尝试三种硬币,一共27步,与递归算法相比,没有任何重复计算。算法时间复杂度:273 O(NM)

例题:

Leetcode 322. Coin Change

You are given coins of different denominations and a total amount of money amount. Write a function to compute the fewest number of coins that you need to make up that amount. If that amount of money cannot be made up by any combination of the coins, return -1.

Example 1:

Input: coins = [1, 2, 5], amount = 11
Output: 3
Explanation: 11 = 5 + 5 + 1
Example 2:

Input: coins = [2], amount = 3
Output: -1

Note:
You may assume that you have an infinite number of each kind of coin.

class Solution {
    public int coinChange(int[] coins, int amount) {
        int[] f = new int[amount+1];
        int n = coins.length;
        
        // initialization
        f[0] = 0;
        for(int i=1; i<=amount; ++i){
            f[i] = Integer.MAX_VALUE;
            // last coin
            for(int j=0; j<n; ++j){
                if(i>=coins[j] && f[i-coins[j]]!=Integer.MAX_VALUE){
                    f[i] = Math.min(f[i-coins[j]]+1, f[i]);
                }
            }
        }
        
        if(f[amount]==Integer.MAX_VALUE) {
            f[amount] = -1;
        }
        return f[amount];
    }
}
### picoCTF Burp Suite 题目 intro to burp 解题思路 在 picoCTF 比赛中,Burp Suite 是一个常用的工具,尤其在 Web 渗透测试相关的题目中。以下是对 `intro to burp` 题目的解题思路的详细分析。 #### 1. 理解题目背景 `intro to burp` 题目通常要求参赛者熟悉 Burp Suite 的基本功能,例如拦截 HTTP 请求、修改请求参数以及观察响应内容。Burp Suite 是一款功能强大的 Web 渗透测试工具,能够帮助用户捕获和分析 HTTP/HTTPS 流量[^1]。 #### 2. 配置 Burp Suite 首先需要确保 Burp Suite 已正确配置,并且浏览器流量被代理到 Burp Suite 上。以下是具体步骤: - 启动 Burp Suite 并打开 Proxy 模块。 - 配置浏览器代理设置为 `127.0.0.1:8080`(默认端口)。 - 在浏览器中访问目标网站,确保所有流量通过 Burp Suite 捕获。 #### 3. 捕获并分析 HTTP 请求 在 Burp Suite 的 Proxy 模块中,可以查看和修改所有通过代理的 HTTP 请求和响应。对于 `intro to burp` 题目,通常需要完成以下操作: - 捕获目标网站的登录请求或表单提交请求。 - 修改请求中的参数值,例如用户名或密码字段。 - 观察服务器返回的响应,寻找可能的漏洞或提示信息。 #### 4. 利用 Repeater 模块 Burp Suite 的 Repeater 模块允许用户重新发送已捕获的请求,并进行动态修改。对于某些题目,可能需要使用 Repeater 来多次尝试不同的输入值。例如: ```python POST /login HTTP/1.1 Host: target-site.com Content-Type: application/x-www-form-urlencoded username=admin&password=test ``` 通过修改 `username` 和 `password` 的值,可以尝试绕过简单的身份验证机制[^1]。 #### 5. 查找 Flag 在许多 picoCTF 题目中,Flag 通常以特定格式存储在页面源代码或服务器响应中。例如,`<flag>your_flag_here</flag>` 或直接嵌入文本中。利用 Burp Suite 的搜索功能,可以在捕获的响应中快速定位 Flag。 --- ### 示例代码:修改 HTTP 请求 以下是一个使用 Burp Suite 修改 HTTP 请求的示例: ```python # 原始请求 POST /login HTTP/1.1 Host: target-site.com Content-Type: application/x-www-form-urlencoded username=user&password=pass # 修改后的请求 POST /login HTTP/1.1 Host: target-site.com Content-Type: application/x-www-form-urlencoded username=admin&password=test ``` --- ### 注意事项 - 确保在合法环境中使用 Burp Suite,避免对未经授权的目标进行攻击[^2]。 - 如果题目涉及更复杂的漏洞(如 SQL 注入或 XSS),需要结合相关知识进行分析和利用[^3]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值