算法分析与设计--动态规划
矩阵链乘
矩阵链乘积是给定一序列矩阵,期望求出相乘这些矩阵的最有效方法。此问题并不是真的去执行其乘法,而只是决定执行乘法的顺序而已。
因为矩阵乘法具有结合律,所有其运算顺序有很多种选择。换句话说,不论如何括号其乘积,最后结果都会是一样的。下列简略证明一下为什么矩阵链乘是可结合的。
上面两个式子都等于
但括号其乘积的顺序是会影响到需计算乘积所需简单算术运算的数目,即其效率。
A 是10 × 30的矩阵, B 是30 × 5矩阵, and C 是5 × 60 矩阵
(AB)C=(10×30×5)+(10×5×60)=1500+3000=4500(AB)C = (10×30×5) + (10×5×60) = 1500 + 3000 = 4500(AB)C=(10×30×5)+(10×5×60)=1500+3000=4500
A(BC)=(30×5×60)+(10×30×60)=9000+18000=27000A(BC) = (30×5×60) + (10×30×60) = 9000 + 18000 = 27000A(BC)=(30×5×60)+(10×30×60)=9000+18000=27000
明显地,第一种方式要有效多了。既然已确认过此问题了,那要如何决定n个矩阵相乘的最佳顺序呢?
我们通过一个数组 p[]
用于保存每个矩阵的行和列。比如上面三个矩阵我们需要一个长度为4的数组,
p[0]
=10
p[1]
=30
p[2]
=5
p[3]
=60
假设将矩阵已经链乘到剩下最后两个矩阵,那么这两个矩阵乘起来的操作数是:op(A)+op(BCD)+p[0]*p[1]*p[4]
递归出口是只操作一个矩阵。
public static int matrixChainOrder(int i,int j,int[] p){//第i个矩阵到第j个矩阵之间最少的链乘操作数。if(i==j)return 0;int min=Integer.MAX_VALUE;for(int k=i;k<j;k++){//要有一个k,用于分割int cur_min=matrixChainOrder(i,k,p)+matrixChainOrder(k+1, j, p)+p[i-1]*p[k]*p[j];if(cur_min<min)min=cur_min;}return min;}
一般可以用递归解决的,都可以用动态规划。通过建表。
public static int matrixChainOrder(int[] p) {int[][] table = new int[p.length][p.length];for (int i = 1; i < table.length; i++)table[i][i] = 0;//l是链的长度。for (int l = 2; l < table.length; l++) {for (int i = 1; i < table.length - l + 1; i++) {int j = i + l - 1;table[i][j] = Integer.MAX_VALUE;for (int k = i; k < j; k++) {int cost = table[i][k] + table[k + 1][j] + p[i - 1] * p[k] * p[j];if (cost < table[i][j])table[i][j] = cost;}}}return table[1][p.length - 1];}
合并石子堆
石子堆合并问题
n堆石子堆,每堆石子个数可能不一样,用数组来保存每堆石子的个数,只能合并两堆相邻的石子。每合并一次,就有一个工作量,工作量是合并两个石子堆的石子数之和。
经过n-1次合并成一个,求最少工作量。
这道题和上述矩阵链乘十分相似。
- 递归解法
public static int minWork1(int[] arr, int i, int j) {// 合并石子堆,递归算法if (i == j)return 0;int cur_min = Integer.MAX_VALUE;for (int k = i; k < j; k++) {int a = minWork1(arr, i, k) + minWork1(arr, k + 1, j) + work(arr, i, j);if (a < cur_min)cur_min = a;}return cur_min;}public static int work(int[] arr, int i, int j) {int sum = 0;for (int k = i; k <= j; k++) {sum = sum + arr[k];}return sum;}
2.动态规划
public static int work(int[] arr, int i, int j) {int sum = 0;for (int k = i; k <= j; k++) {sum = sum + arr[k];}return sum;}public static int minWork2(int[] arr) {//动态规划int[][] table = new int[arr.length][arr.length];for (int i = 0; i < table.length; i++)table[i][i] = 0;for (int l = 2; l <= table.length; l++) {for (int i = 0; i < table.length - l + 1; i++) {int j = i + l - 1;int min = Integer.MAX_VALUE;for (int k = i; k < j; k++) {int a = table[i][k] + table[k + 1][j] + work(arr, i, j);if (a < min)min = a;}table[i][j] = min;}}return table[0][table.length - 1];}
- 利用链表
public static int minWork(ArrayList<Integer> stone) {int sum = 0;while (stone.size() > 1) {int min = stone.get(0) + stone.get(1);int s = 0;for (int i = 1; i < stone.size() - 1; i++) {//找到最小的相邻的两个石子堆之和,并且用s跟踪int a = stone.get(i) + stone.get(i + 1);if (a < min) {min = a;s = i;}}//将两个石子堆删除,添加两个石子堆之和stone.remove(s);stone.remove(s);stone.add(s, min);sum = sum + min;}return sum;}
最长公共子序列
给定两个序列,找出两个序列中存在的最长子序列的长度。子序列是以相同的相对顺序出现,但不一定是连续的序列。例如,“ abc”,“ abg”,“ bdf”,“ aeg”,“ acefg”等是“ abcdefg”的子序列。
思路:
X1 X2 X3 X4……Xn
X1 X2 X3 X4……Xm
我们假设 两个字符串的最长公共子序列长度为 lcs(s1[1……n],s2[1……m])
(1)如果x1=x1,则继续求后面两个的子字符串的公共子序列长度。lcs(s1[1……n],s2[1……m])=1+lcs(s1[2……n],s2[2……m])
(2)如果x1≠x1。
lcs(s1[1……n],s2[1……m])=max(lcs(s1[1……n],s2[2……m]),lcs(s1[2……n],s2[1……m]))
s1中的x1可能是公共子序列的第一个字符。那么s1和s2的最长公共子序列就是求绿色框里的最长公共子序列。
s2中的x1可能是公共子序列的第一个字符。那么s1和s2的最长公共子序列就是求红色框里的最长公共子序列。
public static int longestCommonSubsequence(String text1,String text2){if(text1.length()==0||text1.length()==0)return 0;if(text1.charAt(0)==text2.charAt(0))return 1+longestCommonSubsequence(text1.substring(1), text2.substring(1));elsereturn Math.max(longestCommonSubsequence(text1, text2.substring(1)), longestCommonSubsequence(text1.substring(1), text2));}
子序列的问题很多是可以通过动态规划来解决的。此时我们需要一个表格,动态规划就是通过空间换取时间,所以很多动态规划都可以通过建立表格来求解。
例如
s1=“abefd”
s2=“aeg”
“” | a | b | e | f | g | |
---|---|---|---|---|---|---|
“” | 0 | 0 | 0 | 0 | 0 | 0 |
a | 0 | |||||
e | 0 | |||||
g | 0 | 答案 |
空串和任何字符串都没有公共子序列,所以长度为0;
如果s2[i]==s1[j]s2[i]==s1[j]s2[i]==s1[j]
table[i][j]=1+table[i−1][j−1]table[i][j]=1+table[i-1][j-1]table[i][j]=1+table[i−1][j−1]
否则
table[i][j]=max(table[i][j−1],table[i−1][j])table[i][j]=max(table[i][j-1],table[i-1][j])table[i][j]=max(table[i][j−1],table[i−1][j])
用表格还有另一个好处,就是填写表格十分容易。
最大子段和
算法分析与设计--动态规划相关推荐
- 程振波 算法设计与分析_算法分析与设计之动态规划
动态规划同样是一种将问题分解为求解子问题的方法,不过与分治不同的是,动态规划算法的子问题不是相互独立的,而是有公共的部分,即有重叠子问题,这个时候使用分治算法,将会重复计算公共的子问题,效率很低!而用 ...
- Python算法分析与设计实验:动态规划算法
Python算法分析与设计实验:动态规划算法 一.实验目的 1.理解动态规划求解优化问题的典型步骤,以及动态规划算法求解计算问题的时间复杂度分析 2.熟练掌握利用动态规划算法求解一维.二维等典型优化问 ...
- 《算法分析与设计》课程任务
<算法分析与设计>课程任务 内容包括以下8个部分,建议将任务按以下方式分解:其中1-6的每个部分的简介.适用条件.基本思想.基本步骤.复杂度分析等由1人讲解,实例分析由1人讲解(注:至少一 ...
- 用c语言验证装载问题 回溯法,《算法分析与设计》期末考试复习题纲(完整版)...
<算法分析与设计>期末复习题 一.选择题 1. 算法必须具备输入.输出和( D )等4个特性. A.可行性和安全 性 B .确定性和易读性 C.有穷性和安全 性 D .有穷性和确定性 2. ...
- 东师19年春计算机在线作业,东师算法分析与设计20春在线作业1【标准答案】
算法分析与设计20春在线作业1题目 试卷总分:100 得分:100 一.单选题 (共 20 道试题,共 40 分) 1.按F5开始调试,程序便会直接运行到断点处.接下来可以逐行来运行程序,查看各个变 ...
- 算法分析与设计实验报告——实现汽车加油问题
算法分析与设计实验报告--实现汽车加油问题 目录: 算法分析与设计实验报告--实现汽车加油问题 一. 实验目的 二.实验要求 三. 实验原理 四. 实验过程(步骤) 五. 运行结果 六.实验分析与讨论 ...
- 算法分析与设计期末总结
这是我的算法分析与设计课程自己总结的一些知识点,应该不太全,记录一下 算法的特征: 输入,输出,确定性,有穷性,可行性 基本数据结构: 线性,树结构,图结构,集合 递归与分治 1.递归法 使用递归 ...
- 数学之美系列二十四 -- 谈谈动态规划与如何设计动态规划算法
数学之美--动态规划 今 年九月二十三日,Google.T-Mobile 和 HTC 宣布了第一款基于开源操作系统 Android 的 3G 手机,其中一个重要的功能是利用全球卫星定位系统实现全球导航 ...
- Java算法分析与设计视频教程
分享一套牛牧老师的<实战应用Java算法分析与设计(链表.二叉树.哈夫曼树.图.动态规划.HashTable算法)>视频教程,通过本课程的学习,学员可以掌握以下技术点:线性结构与顺序表.单 ...
最新文章
- MySQL索引类型一览 让MySQL高效运行起来
- hadoop 运行java程序_Hadoop java 程序运行
- F#学习之路(3) 如何组织程序(下)
- kafka_consumer_消费原理介绍
- python文件实时同步_python文件自动同步备份v1.2【运维必备】2020/12/31
- oracle 10g分区表,oracle10g--11gR2分区表汇总四
- Java关键字---this的由来和其三大作用
- Linus Torvalds 回应,Debian 项目曾讨论永久禁止他出席会议!
- LoRa网关的特点及应用
- 使用Syncthing文件同步工具在两台Windows server服务器实现文件同步(实战)
- Flask 中 AssertionError: View function mapping is overwriting an existing endpoint function: decorate
- win10出现“以太网没有有效的ip配置”的问题
- android 仿微信账单生成器手机版式,2020微信年度账单生成器
- 打开终端如何自动进入conda环境
- 数据运营-数据管理平台
- c语言程序设计 大学考试题库,广东工业大学《C语言程序设计》考试复习重点题库.pdf...
- Vite-babysitter 像月嫂?保姆?照顾孩子一般为你讲解Vite源码。
- function* 生成器函数
- Oracle 11gR2 新技术 Cardinality Feedback
- No boot filename received