Day3

  • Day3-part1
    • 问题描述
    • 公共子序列解决思路
      • 递推公式的确定
    • 获取序列信息
  • Day3-part2
    • 问题描述
    • 0/1背包解决思路
    • 找到具体放入的物品
    • 一种可行的解决方案

Day3-part1

Longest Common Subsequence 最长公共子序列问题

问题描述

这里主要想解决的问题是,确定两个字符串所包含的公共序列,允许字符之间存在间隙,但是不允许改变字符之间的顺序,例如:
序列1: GATTACA
序列2: TACTGTC
最长公共子序列显然为: ATTC, 但是如何确定公共子序列最大长度,以及具体是什么呢?

公共子序列解决思路

[1 ] 确定dp数组(dp table)以及下标的含义
[2 ] 确定递推公式
[3 ] dp数组如何初始化
[4 ] 确定遍历顺序
[5 ] 举例推导dp数组

我们解决这个问题,如果分别从两个序列的头部向后看,比如现在:
S_source=GATTACA
S_target=TACTGTC
从target第一个元素开始看起

GATTACT
TAC
此时LCS=3,因为S_target后续元素T,在source中找不到了,最大的长度就为3!

同理,如果反过来看呢:

TACTGTC
GATTACA
此时LCS=3,因为后续元素找不到了,最大的长度就为3!

因此,很自然我们可以想到,想获取最长公共子序列,需要两个字符串序列,分别去对方的序列中寻找,那么dp数组应该是一个二维数组。dp数组每个位置的含义是什么呢?
dp[i][j] 对应的是 S_target[0:j] 在序列 S_source[0:i] 中, 两者对应的最大公共子序列。
比如: dp[0][5]对应的是 ‘G’ 在序列 ‘TACTGT’ 中的公共子序列长度, 显然为1
比如: dp[3][5]对应的是 ‘GATT’ 在序列 ‘TACTGT’ 中的公共子序列长度, 显然为3

s_source='GATTACA'
s_target='TACTGTC'
dp=[[0 for i in range(len(s_target))] for j in range(len(s_source))]

下图为对应生成的二维数组,并且全部由0充满

那么,我们应该对dp数组进行初始化。根据如上的分析,很容易对第一行和第一列进行初始化

for i in range(len(s_target)):if s_source[0]==s_target[i]:for j in range(i,len(s_traget)):result[0][j]=1break
for i in range(len(s_source)):if s_target[0]==s_source[i]:for j in range(i,len(s_source)):result[j][0]=1break

递推公式的确定

动态规划的核心是确定递推公式,针对很多问题应该首先确定递推公式,随后确定dp数组初始化,但是在这里的话,为了针对分析的便利显示,我们首先将图绘出,进行分析。
针对问号点的数值我们应该如何确定呢?

针对点dp[ i ] [ j ],如果满足s_source[ i ] == s_target[ j ]的话,那公共子序列的长度肯定就会+1
是针对谁+1呢? 显然是针对dp[ i-1 ] [ j-1 ]的数值+1, 即针对上一个状态+1
if s_source[ i ] == s_target[ j ] dp[ i ] [ j ]=dp[ i-1 ] [ j-1 ]+1
当时当 s_source[ i ] != s_target[ j ],现在应该执行什么操作呢?
想一想~
那现在肯定不能是前一个状态+1了,甚至说,都不应该考虑+1的事情了!
但是现在还是想知道公共子序列的最长长度,那么现在dp[ i ] [ j ] 应该就是对应未进入i,j状态的最大值了!
dp[ i ] [ j ] =max(dp[ i-1 ] [ j ],dp[ i ] [ j-1 ])
if s_source[ i ] != s_target[ j ] dp[ i ] [ j ]=max(dp[ i-1 ] [ j ],dp[ i ] [ j-1 ])



for i in range(1,len(s_source)):for j in range(1,len(s_target)):if s_source[i]==s_target[j]:dp[i][j]=dp[i-1][j-1]+1else:dp[i][j]=max(dp[i-1][j],dp[i][j-1])

至此,可以获得完全的dp矩阵,最大子序列长度应当出现在dp[ len(s_source)-1 ][ len(s_target)-1 ]
即右下角的点的值!

获取序列信息


如何获得子序列信息分别是什么呢?
需要进行的操作是从右下角开始寻找,逐步往上或者往左移动,标记dp[ i ][ j ] >dp[ i-1 ][ j ] 同时dp[ i ][ j ] >dp[ i ][ j-1 ]的点,对应的字符即为我们想知道的子序列

common_string=[]
i=len(s_source)-1
j=len(s_target)-1
while(i>=1 and j>=1):if dp[i][j]>dp[i-1][j] and dp[i][j]>dp[i][j-1]:common_string.append((s_source[i]))i-=1j-=1elif dp[i][j]==dp[i-1][j]:i-=1elif dp[i][j]==dp[i][j-1]:j-=1
return common_string

Day3-part2

The 0/1 knapsack Problem 0/1背包问题

问题描述

你有一个背包需要填充,背包的体积容量有要求。针对每个物品,你只可以选择0件/1件。每个物品有自己的体积(重量),和他对应的价值,现在你要做的事情:合理选择物品获得背包最大价值!
物品(items):( wi , valuei ) 物品重量、价值
(3,9);(1,7);(12,18);(5,3);(2,11)
背包容量:10 最大价值:9+7+11=27 选择物品:3+1+2
穷举的话,肯定是可以举出来的,但是这是否有点太暴力了。
我们在这里想一下用动态规划怎么来做呢?

0/1背包解决思路

[1 ] 确定dp数组(dp table)以及下标的含义
[2 ] 确定递推公式
[3 ] dp数组如何初始化
[4 ] 确定遍历顺序
[5 ] 举例推导dp数组

第一步,确定dp数组,这里的dp数组我们首先想到的是,延续part1的思路,我们构建一个二维数组。
整个二维数组,row=len(items), column=weight+1。
行代表是否放入某个物品进行考虑,列代表针对不同容量的背包从0容量开始考虑。
dp[ i ][ j ] 代表目前情况下背包内能放下的最大价值。

第二步,确定递推公式。
针对任意的 i,j。i 代表是否要放入物品 i ,j 代表的是当前的背包容量。 很直观我们想到的是双重循环,先遍历 i 再遍历 j。针对dp[ i ][ j ],肯定要取当前能取到的最大值,才能确保背包含有的价值是最大值。
dp[ i ][ j ]的取值无非是两种情况:

  • 不放入items[ i ],那么dp[ i ][ j ]=dp[ i-1 ][ j ] ,也就是说和不放入的情况一模一样喽!
  • 如果放入items[ i ],那么dp[ i ][ j ]=dp[ i-1 ][ j-items[ i ][ 0 ] ]+items[ i ][ 1 ] (这个不懂看图)

    现在看我画圈圈的地方,现在是不是针对背包容量为5,考虑item(1,7)的情况!
    如果不放入item的话,那么dp[ i ][ j ]=9
    如果放入item的话,那么就相当于上一行背包容量为4的时候的值**(黄色点)**,再加上item(1,7),dp[ i ][ j ]=9+7=16,这两个取最大值就是这个红色圈圈应该放进去的值,对吧!
    dp[ i ][ j ]=max(dp[ i-1 ][ j ], dp[ i-1 ][ j-items[ i ][0]] +items[ i ][ 1 ])

第三步,dp数组初始化
这一步也很简单的对吧!因为最开始肯定是空空荡荡的背包喽,每个点的价值都会是0!
dp[ i ][ j ]=0,千真万确。

第四步,确定遍历顺序
遍历顺序:先行后列,前面有说过,那么现在通过我们的代码实现吧!

value=[[3,9],[1,7],[12,18],[5,3],[2,11]
] #前项代表重量,后项代表价值
def get_max_value(weight):dp=[[0 for i in range(weight+1)] for j in range(len(value)+1)]for i in range(1,len(value)+1):for j in range(1,weight+1):if j >=value[i-1][0]:dp[i][j]=max(dp[i-1][j],dp[i][j-value[i-1][0]]+value[i-1][1])else:dp[i][j]=dp[i-1][j]return dp[len(value)][weight]

def get_max_value(weight):dp=[[0 for i in range(weight+1)]for j in range(len(value))]for i in range(value[0][0],weight+1):dp[0][i]=value[0][1]for i in range(1,len(value)):for j in range(0,weight+1):if j>=value[i][0]:dp[i][j]=max(dp[i-1][j],dp[i-1][j-value[i][0]]+value[i][1])else:dp[i][j]=dp[i-1][j]return dp[len(value)-1][weight]

这就是执行完的样子了,右下角就是最大价值了,自己动手实现一下吧!

找到具体放入的物品

那么,我们怎么才能知道具体放入了什么物品呢

因为在dp数组中,最后一列代表着背包容量为weight的最大价值,那么在这里对最后一列进行分析。

27-16=11 筛选出item(2,11)
16-9=7 筛选出item(1,7)
9-0=9 筛选出item(3,9)
最终得到结果 item(2,1,3)

这里理解怎么出来的就好,基本上不会让你去实现的,fine!
现在pdf上面的内容就实现完了!Day3你已经成功拿下了!

一种可行的解决方案

现在我们的dp数组是一个二维数组对吧!这肯定会占用很大的存储空间,我们用一维数组能不能处理这个事情呢,可以的,是可以的。

数组递推方法:

dp[ i ]=max(dp[ i ],dp[ i-items[ i ][ 0 ] ]+items[ i ][ 1 ] )
还是考虑两种情况,是否放入items[i]
如果不放入: dp[ i ]=dp[ i ]
如果放入: dp[ i ]=dp[ i-items[ i ][ 0 ] ]+items[ i ][ 1 ] 想一下为什么呢?其实和二维是一样的,就是预留容量价值 + 物品价值!
两者取最大值是不是就完事了!

数组初始化:
初始均为0

def max_value(weight):dp=[0]*(weight+1)for i in range(len(value)):for j in range(weight,value[i][0]-1,-1):dp[j]=max(dp[j],dp[j-value[i][0]]+value[i][1])return dp[weight]

注意仔细阅读两层循环嵌套,第二层循环嵌套,是不是逆向进行的? 为什么要逆向呢?
自己想一下,如果是正向的话,如果重量满足情况,在不断更新中,是不是将这个物体重复放入了,这样就不是 0/1背包 问题了!

自己动手实现吧,辛苦了!

海客谈瀛洲,烟涛微茫信难求。

越人语天姥,云霞明灭或可睹。

天姥连天向天横,势拔五岳掩赤城。

天台一万八千丈,对此欲倒东南倾。

我欲因之梦吴越,一夜飞度镜湖月。

Python Prep随想练习-Day3相关推荐

  1. Python prep 随想练习 Day7-红黑树

    Day7 Day7-part1 平衡二叉树 AVL LL型失衡 RR型失衡 LR型失衡 RL型失衡 Red-Black 恢复平衡操作 插入节点分析 场景一:红黑树为空树 场景二:插入节点的父节点为黑色 ...

  2. python全栈学习--day3

    一.基础数据类型 基础数据类型,有7种类型,存在即合理. 1.int 整数 主要是做运算的 .比如加减乘除,幂,取余  + - * / ** %... 2.bool 布尔值 判断真假以及作为条件变量 ...

  3. ql的python学习之路-day3

    字典操作 特性: 1.无序的 2.key是唯一的 #!/usr/bin/env python# -*- coding utf-8 -*-# Author:qinjiaxiinfo = {'name1' ...

  4. 【Python数据分析学习笔记Day3】(三)数据分析工具pandas,数据清洗,聚类K-Means

    Pandas学习 https://blog.csdn.net/qq_41251963/article/details/103904044 Pandas数据结构 import pandas as pd ...

  5. Python全栈开发 day3

    111 转载于:https://www.cnblogs.com/sharef/p/9418979.html

  6. 魔兽世界是用什么游戏引擎_战略游戏必须向1994年的《魔兽世界》学习的一件事...

    魔兽世界是用什么游戏引擎 回顾性 (RETROSPECTIVE) Warcraft: Orcs & Humans is a fascinating game. It's an experien ...

  7. python 闭包变量不允许write,要使用nonlocal

    以下是一段简单的闭包代码示例: def foo():m=3n=5def bar():a=4return m+n+a return bar >>>bar = foo() >> ...

  8. python内置函数open_Python的内置函数open()的注意事项

    用法 : open("file_address","open_mode") 例子 : f = open("D:\PycharmProjects\log ...

  9. Python中global和nolocal作用域的理解

    原创:https://www.cnblogs.com/z360519549/p/5172020.html python引用变量的顺序: 当前作用域局部变量-> 闭包函数外的函数中变量->当 ...

  10. 最新python全栈3期高级开发工程师 独家完整版

    课程目录: │   ├─1-10 │  │   │  ├─day01 │  │      01 python全栈s3 day1 计算机发展史.mp4 │  │      02 python全栈s3 d ...

最新文章

  1. stm32 can bus 总结
  2. (*长期更新)软考网络工程师学习笔记——Section 7 网络层下篇
  3. ArcGIS API for Silverlight地图加载众多点时,使用Clusterer解决重叠问题
  4. 【HDU - 6203】ping ping ping(lca+贪心思想,对lca排序,树状数组差分)
  5. 使用.NET读取XML文件
  6. linux需要你的不懈努力
  7. python中if控制语句_Python 极简教程(十二)逻辑控制语句 if else
  8. 基于表征(Representation)的文本匹配、信息检索、向量召回的方法总结
  9. python分支结构基础实训_python-002基础——分支结构
  10. StringUtil工具类之去除所有的空白字符
  11. 基于python的数字印刷体识别_不告诉你我用了它配合Python简简单单开发OCR识别,带你识别手写体、印刷体、身份证等N种,附代码!...
  12. java根据http url下载图片
  13. 轴承后缀ce和ca_轴承cc和ca与cde4有什么区别
  14. wx.getLocation() 定位误差 解决
  15. 【仿真】后仿真中的notifier是奏啥滴!
  16. 《程序员》11期最新上市:互联网架构集结号
  17. 解除应用计算机仿真,语音识别中计算机仿真的应用
  18. VSCode 无法跳转到定义
  19. 亚信安全与新华三联手打造“更安全”的云数据中心
  20. Git 不忽略某个文件

热门文章

  1. Gallery3d 学习笔记(6)
  2. 多声道音频指南(二)—— 前世与今生
  3. linpack测试软件,服务器性能测试(linpack,stream,netperf,iometer)
  4. spark学习五——归属地计算案例
  5. Guava Cache 过期回源
  6. 实话实说,现在的结婚,真就是走个形式!
  7. 链接:https://pan.baidu.com/s/1o3FMGQfAd1sa5XWgiO1jXA 提取码:sltl OPENCV的资料库
  8. dropbox连接不上解决方法
  9. 项目组自己编写的js分页标签(百度分页)
  10. visio画立体图_Microsoft Office Visio绘制三维正方体图形的详细操作步骤