动态规划求解24点游戏原理
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
计算机算法与应用开发结合 系列讲座
动态规划算法 求解24点游戏
程欣宇 2017年7月5日
提纲
• 一、动态规划算法
• 二、最长公共子序列问题 • 三、24点游戏
1.1 动态规划算法的位置
计 算 机 算 法 设 计 与 分 析
分支限界法
系 统 地 分 解 问 题
铺开多种方案同时搜索 深究一个方案是否可行 解决子问题重复的性能低下问题
空 空 D C B C A 0 0 0 0 0 0 0
10
A 0
B 0
A 0
C 0
B 0
B
2.4 计算最优值
由于在所考虑的子问题空间中,总共有θ(mn)个不同的子问题,因 此,用动态规划算法自底向上地计算最优值能提高算法的效率。
void LCSLength(int m,int n,char *x, char *y,int **c,int **b) { int i,j; for (i = 1; i <= m; i++) c[i][0] = 0; for (i = 1; i <= n; i++) c[0][i] = 0; for (i = 1; i <= m; i++) for (j = 1; j <= n; j++) { if (x[i]==y[j]) { c[i][j]=c[i-1][j-1]+1; b[i][j]=1;} else if (c[i-1][j]>=c[i][j-1]) { c[i][j]=c[i-1][j]; b[i][j]=2;} else { c[i][j]=c[i][j-1]; b[i][j]=3; } } }
7
2.1 最长公共子序列
•若给定序列X={x1,x2,…,xm},则另一序列 Z={z1,z2,…,zk},是X的子序列是指存在一个严格递增下 标序列{i1,i2,…,ik}使得对于所有j=1,2,…,k有:zj=xij。例 如,序列Z={B,C,D,B}是序列X={A,B,C,B,D, A,B}的子序列,相应的递增下标序列为{2,3,5,7}。 •给定2个序列X和Y,当另一序列Z既是X的子序列又是 Y的子序列时,称Z是序列X和Y的公共子序列。 •给定2个序列X={x1,x2,…,xm}和Y={y1,y2,…,yn},找出 X和Y的最长公共子序列。
8
2.2 最长公共子序列的结构
设序列X={x1,x2,…,xm}和Y={y1,y2,…,yn}的最长公共子序列为 Z={z1,z2,…,zk} ,则 (1)若xm=yn,则zk=xm=yn,且zk-1是xm-1和yn-1的最长公共子序列。 (2)若xm≠yn且zk≠xm,则Z是xm-1和Y的最长公共子序列。 (3)若xm≠yn且zk≠yn,则Z是X和yn-1的最长公共子序列。 由此可见,2个序列的最长公共子序列包含了这2个序列的前缀 的最长公共子序列。因此,最长公共子序列问题具有最优子结 构性质。
如何让计算机避免以上问题? 1.系统搜索:避免跳跃和发散。 2.压缩状态空间:避免记忆力有限(内存不足)和大脑疲劳 (计算时间过长),比如2+3和3+2不必记忆两次。
3.3 定义问题和子问题
设运算符集合O={o1,o2,..,om}={+,-,x,÷} 原问题Q:运算数集合A={a1,a2,..an},要求一个表达式,使用n-1 个运算连接这n个数,求出所有可能的运算结果,保留其中为r=24 的结果。 1级子问题S:运算数集合Ai={a1,a2,..an} - ai,要求一个表达式, 使用n-2个运算连接这n-1个数,求出所有可能的运算结果,保留 所有结果。 原问题和子问题的关系: result(A)= combine(a1,A1)+combine(a2,A2)+..combine(an,An) 举例: result(3,3,8,8)={3+result{3,8,8),3-result{3,8,8),..3÷result{3,8,8), 8+result{3,3,8),8-result{3,3,8),..8÷result{3,3,8)}
3.4 面向对象的实现要点
1. 厘清所有涉及的概念之间的关系: 操作数、运算符、表达式、交换律 操作数是一种表达式; 交换律是某些运算符的一种特性; 2. 类图
3.5 关键数据结构设计
分数类型: 鉴于除法运算可能损失精度,如1/3=0.3333333。而 0.3333333×3=0.9999999。会影响最终结果的判断。所以设计分 数类型Fraction,仅有两个成员:分子和分母。普通数仅有分子, 默认分母为1。这样才能支持8-(3-8/3)=24。 备忘录: 从数字集合到运算结果集合的映射表。
11
3.1 24点游戏
任意给4个数,要求用四则运算将这4个数计算得到24。
例:{3,3,8,8}, {10,12,6,9}
3.2 还原和改进大脑的思考过程
以{10,12,6,9}为例,多数人会这样思考: 1.把6单独拿出来,看看能不能用10,6,9凑一个4, 如果能,就可以得到6x4=24。 2.把10单独拿出来,看看12,6,9能不能凑一个14, 如果能,就可以10+14=24。 ...... 人脑为什么会搜索漏答案? 人脑的缺陷:1.记忆力有限,2.思维跳跃、发散,3.大脑疲劳
构造最长公共子序列
void LCS(int i,int j,char *x,inБайду номын сангаас **b)
{ if (i ==0 || j==0) return; if (b[i][j]== 1){ LCS(i-1,j-1,x,b); cout<<x[i]; } else if (b[i][j]== 2) LCS(i-1,j,x,b); else LCS(i,j-1,x,b); }
回溯算法
动态规划
分治算法 贪心算法
解决大问题的划小问题
简单快速解决问题,不一定准确
1.1 动态规划算法总体思想
动态规划算法与分治法类似,其基本思想也是将待求解问题分解 成若干个子问题
T(n)
=
n
T(n/2)
T(n/2)
T(n/2)
T(n/2)
1.1 动态规划算法总体思想
但是经分解得到的子问题往往不是互相独立的。不同子问题的数 目常常只有多项式量级。在用分治法求解时,有些子问题被重复 计算了许多次。
Dictionary<string, SortedList<Fraction, Expression>> memo; 如memo[‘2,3’]= {<-1,2-3>, <2/3,2÷3>, <1,3-2>, <3/2, 3÷2>, <5, 3+3>, <6, 3×3>};
3.6 关键性能优化
动态规划的备忘录用法:每划分出一个子问题时,先查子问 题是否已经求解,如果是,则直接取结果,否则才计算子问 题,计算完成以后,把结果放入备忘录。 状态空间压缩: 压缩等价状态,如memo{3,8}和memo{8,3},办法是进行 排序,则8,3会等于3,8,避免了重复计算和占用备忘录。 压缩等价计算,如2+3=3+2,利用交换律,只计算存储 其中一个。但2*2和2+2不能只存储一个。
3.7 代码运行演示
谢谢!讨论!
T(n)
n/2
T(n/4) T(n/4) T(n/4)
=
n
n/2 n/2
T(n/4)
6
n/2
T(n/4)
T(n/4) T(n/4) T(n/4)T(n/4)T(n/4) T(n/4)
1.2 动态规划基本步骤
• 找出最优解的性质,并刻划其结构特征。 • 递归地定义最优值。 • 以自底向上的方式计算出最优值。 • 根据计算最优值时得到的信息,构造最优解。
T(n)
n/2
=
n/2
n
n/2 n/2
T(n/4)T(n/4)T(n/4)T(n/4) T(n/4)T(n/4)T(n/4)T(n/4) T(n/4)T(n/4)T(n/4)T(n/4) T(n/4)T(n/4)T(n/4)T(n/4
5
1.1 动态规划算法总体思想
如果能够保存已解决的子问题的答案,而在需要时再找出已求得 的答案,就可以避免大量重复计算,从而得到多项式时间算法。
序列X: 序列Y:
序列Z:
X1 Y1 Z1
Xn Ym Zk
D
A C
B B
A C .
C A .
B B B
2.3 子问题的递归结构
由最长公共子序列问题的最优子结构性质建立子问题最优值的递归 关系。用c[i][j]记录序列和的最长公共子序列的长度。其中, Xi={x1,x2,…,xi};Yj={y1,y2,…,yj}。当i=0或j=0时,空序列是Xi和Yj的 最长公共子序列。故此时C[i][j]=0。其它情况下,由最优子结构性 质可建立递归关系如下: 0 i 0, j 0 c[i ][ j ] c[i 1][ j 1] 1 i, j 0; xi y j max{ c[i ][ j 1], c[i 1][ j ]} i, j 0; xi y j
动态规划算法 求解24点游戏
程欣宇 2017年7月5日
提纲
• 一、动态规划算法
• 二、最长公共子序列问题 • 三、24点游戏
1.1 动态规划算法的位置
计 算 机 算 法 设 计 与 分 析
分支限界法
系 统 地 分 解 问 题
铺开多种方案同时搜索 深究一个方案是否可行 解决子问题重复的性能低下问题
空 空 D C B C A 0 0 0 0 0 0 0
10
A 0
B 0
A 0
C 0
B 0
B
2.4 计算最优值
由于在所考虑的子问题空间中,总共有θ(mn)个不同的子问题,因 此,用动态规划算法自底向上地计算最优值能提高算法的效率。
void LCSLength(int m,int n,char *x, char *y,int **c,int **b) { int i,j; for (i = 1; i <= m; i++) c[i][0] = 0; for (i = 1; i <= n; i++) c[0][i] = 0; for (i = 1; i <= m; i++) for (j = 1; j <= n; j++) { if (x[i]==y[j]) { c[i][j]=c[i-1][j-1]+1; b[i][j]=1;} else if (c[i-1][j]>=c[i][j-1]) { c[i][j]=c[i-1][j]; b[i][j]=2;} else { c[i][j]=c[i][j-1]; b[i][j]=3; } } }
7
2.1 最长公共子序列
•若给定序列X={x1,x2,…,xm},则另一序列 Z={z1,z2,…,zk},是X的子序列是指存在一个严格递增下 标序列{i1,i2,…,ik}使得对于所有j=1,2,…,k有:zj=xij。例 如,序列Z={B,C,D,B}是序列X={A,B,C,B,D, A,B}的子序列,相应的递增下标序列为{2,3,5,7}。 •给定2个序列X和Y,当另一序列Z既是X的子序列又是 Y的子序列时,称Z是序列X和Y的公共子序列。 •给定2个序列X={x1,x2,…,xm}和Y={y1,y2,…,yn},找出 X和Y的最长公共子序列。
8
2.2 最长公共子序列的结构
设序列X={x1,x2,…,xm}和Y={y1,y2,…,yn}的最长公共子序列为 Z={z1,z2,…,zk} ,则 (1)若xm=yn,则zk=xm=yn,且zk-1是xm-1和yn-1的最长公共子序列。 (2)若xm≠yn且zk≠xm,则Z是xm-1和Y的最长公共子序列。 (3)若xm≠yn且zk≠yn,则Z是X和yn-1的最长公共子序列。 由此可见,2个序列的最长公共子序列包含了这2个序列的前缀 的最长公共子序列。因此,最长公共子序列问题具有最优子结 构性质。
如何让计算机避免以上问题? 1.系统搜索:避免跳跃和发散。 2.压缩状态空间:避免记忆力有限(内存不足)和大脑疲劳 (计算时间过长),比如2+3和3+2不必记忆两次。
3.3 定义问题和子问题
设运算符集合O={o1,o2,..,om}={+,-,x,÷} 原问题Q:运算数集合A={a1,a2,..an},要求一个表达式,使用n-1 个运算连接这n个数,求出所有可能的运算结果,保留其中为r=24 的结果。 1级子问题S:运算数集合Ai={a1,a2,..an} - ai,要求一个表达式, 使用n-2个运算连接这n-1个数,求出所有可能的运算结果,保留 所有结果。 原问题和子问题的关系: result(A)= combine(a1,A1)+combine(a2,A2)+..combine(an,An) 举例: result(3,3,8,8)={3+result{3,8,8),3-result{3,8,8),..3÷result{3,8,8), 8+result{3,3,8),8-result{3,3,8),..8÷result{3,3,8)}
3.4 面向对象的实现要点
1. 厘清所有涉及的概念之间的关系: 操作数、运算符、表达式、交换律 操作数是一种表达式; 交换律是某些运算符的一种特性; 2. 类图
3.5 关键数据结构设计
分数类型: 鉴于除法运算可能损失精度,如1/3=0.3333333。而 0.3333333×3=0.9999999。会影响最终结果的判断。所以设计分 数类型Fraction,仅有两个成员:分子和分母。普通数仅有分子, 默认分母为1。这样才能支持8-(3-8/3)=24。 备忘录: 从数字集合到运算结果集合的映射表。
11
3.1 24点游戏
任意给4个数,要求用四则运算将这4个数计算得到24。
例:{3,3,8,8}, {10,12,6,9}
3.2 还原和改进大脑的思考过程
以{10,12,6,9}为例,多数人会这样思考: 1.把6单独拿出来,看看能不能用10,6,9凑一个4, 如果能,就可以得到6x4=24。 2.把10单独拿出来,看看12,6,9能不能凑一个14, 如果能,就可以10+14=24。 ...... 人脑为什么会搜索漏答案? 人脑的缺陷:1.记忆力有限,2.思维跳跃、发散,3.大脑疲劳
构造最长公共子序列
void LCS(int i,int j,char *x,inБайду номын сангаас **b)
{ if (i ==0 || j==0) return; if (b[i][j]== 1){ LCS(i-1,j-1,x,b); cout<<x[i]; } else if (b[i][j]== 2) LCS(i-1,j,x,b); else LCS(i,j-1,x,b); }
回溯算法
动态规划
分治算法 贪心算法
解决大问题的划小问题
简单快速解决问题,不一定准确
1.1 动态规划算法总体思想
动态规划算法与分治法类似,其基本思想也是将待求解问题分解 成若干个子问题
T(n)
=
n
T(n/2)
T(n/2)
T(n/2)
T(n/2)
1.1 动态规划算法总体思想
但是经分解得到的子问题往往不是互相独立的。不同子问题的数 目常常只有多项式量级。在用分治法求解时,有些子问题被重复 计算了许多次。
Dictionary<string, SortedList<Fraction, Expression>> memo; 如memo[‘2,3’]= {<-1,2-3>, <2/3,2÷3>, <1,3-2>, <3/2, 3÷2>, <5, 3+3>, <6, 3×3>};
3.6 关键性能优化
动态规划的备忘录用法:每划分出一个子问题时,先查子问 题是否已经求解,如果是,则直接取结果,否则才计算子问 题,计算完成以后,把结果放入备忘录。 状态空间压缩: 压缩等价状态,如memo{3,8}和memo{8,3},办法是进行 排序,则8,3会等于3,8,避免了重复计算和占用备忘录。 压缩等价计算,如2+3=3+2,利用交换律,只计算存储 其中一个。但2*2和2+2不能只存储一个。
3.7 代码运行演示
谢谢!讨论!
T(n)
n/2
T(n/4) T(n/4) T(n/4)
=
n
n/2 n/2
T(n/4)
6
n/2
T(n/4)
T(n/4) T(n/4) T(n/4)T(n/4)T(n/4) T(n/4)
1.2 动态规划基本步骤
• 找出最优解的性质,并刻划其结构特征。 • 递归地定义最优值。 • 以自底向上的方式计算出最优值。 • 根据计算最优值时得到的信息,构造最优解。
T(n)
n/2
=
n/2
n
n/2 n/2
T(n/4)T(n/4)T(n/4)T(n/4) T(n/4)T(n/4)T(n/4)T(n/4) T(n/4)T(n/4)T(n/4)T(n/4) T(n/4)T(n/4)T(n/4)T(n/4
5
1.1 动态规划算法总体思想
如果能够保存已解决的子问题的答案,而在需要时再找出已求得 的答案,就可以避免大量重复计算,从而得到多项式时间算法。
序列X: 序列Y:
序列Z:
X1 Y1 Z1
Xn Ym Zk
D
A C
B B
A C .
C A .
B B B
2.3 子问题的递归结构
由最长公共子序列问题的最优子结构性质建立子问题最优值的递归 关系。用c[i][j]记录序列和的最长公共子序列的长度。其中, Xi={x1,x2,…,xi};Yj={y1,y2,…,yj}。当i=0或j=0时,空序列是Xi和Yj的 最长公共子序列。故此时C[i][j]=0。其它情况下,由最优子结构性 质可建立递归关系如下: 0 i 0, j 0 c[i ][ j ] c[i 1][ j 1] 1 i, j 0; xi y j max{ c[i ][ j 1], c[i 1][ j ]} i, j 0; xi y j