用分治法解决问题
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
分治策略解决问题
问题1 问题1:找出伪币
一个装有1 6枚硬币的袋子 一个装有1 6枚硬币的袋子,1 6枚硬币中有一个 枚硬币的袋子, 6枚硬币中有一个 是伪造的, 是伪造的,并且那个伪造的硬币比真的硬币要轻 一些。你的任务是找出这枚伪造的硬币。 一些。你的任务是找出这枚伪造的硬币。 为了帮助你完成这一任务, 为了帮助你完成这一任务,将提供一台可用来比 较两组硬币重量的仪器,比如天平。 较两组硬币重量的仪器,比如天平。利用这台仪 可以知道两组硬币的重量是否相同。 器,可以知道两组硬币的重量是否相同。
找金块的示例图
方法2 方法2:
n≤2,识别出最重和最轻的金块,一次比较就足够 ≤2,识别出最重和最轻的金块, 了。 n>2,第一步,把这袋金块平分成两个小袋A和B。 第一步,把这袋金块平分成两个小袋A 第二步,分别找出在A 中最重和最轻的金块。 第二步,分别找出在A和B中最重和最轻的金块。设 A中最重和最轻的金块分别为HA 与LA,以此类推, 中最重和最轻的金块分别为HA LA,以此类推, B中最重和最轻的金块分别为HB 和LB。第三步, 中最重和最轻的金块分别为HB LB。第三步, 通过比较HA HB,可以找到所有金块中最重的; 通过比较HA 和HB,可以找到所有金块中最重的; 通过比较LA LB,可以找到所有金块中最轻的。 通过比较LA 和LB,可以找到所有金块中最轻的。 在第二步中, 则递归地应用分而治之方法。 在第二步中,若n>2,则递归地应用分而治之方法。
分治思想
所谓分治,就字面意思而言,就是分而治之, 所谓分治,就字面意思而言,就是分而治之,将一个问题 分解成为若干个与原有问题相似但规模较小的子问题, 分解成为若干个与原有问题相似但规模较小的子问题,然 后递归的求解这些子问题, 后递归的求解这些子问题,最后合并这些子问题的结果就 得到原问题的解了。可以用很简单的话来形容分治: 得到原问题的解了。可以用很简单的话来形容分治:“大 事化小,小事化了” 事化小,小事化了”。 有将问题一分为二,也有将问题一分为三或一分为N等份。 有将问题一分为二,也有将问题一分为三或一分为N等份。 对每一等份分别进行解决后,原问题就可以很快得以解决。 对每一等份分别进行解决后,原问题就可以很快得以解决。 因此一个问题能否用分治法解决,关键是看该问题是否能 因此一个问题能否用分治法解决,关键是看该问题是否能 将原问题分成n个规模较小而结构与原问题相似的子问题。 将原问题分成n个规模较小而结构与原问题相似的子问题。 递归的解决这些子问题, 递归的解决这些子问题,然后合并其结果就得到原问题的 解。 n=2时的分治法又称二分法 时的分治法又称二分法。 当n=2时的分治法又称二分法。
基本步骤
一般分为三步递归进行 1.分解:将原问题分解为若干个规模较小,相互独 1.分解 将原问题分解为若干个规模较小, 分解: 与原问题形式相同的子问题; 立,与原问题形式相同的子问题; 2.解决:若子问题规模较小而容易被解决则直接求 2.解决 解决: 否则递归地解各个子问题; 解,否则递归地解各个子问题; 3.合并:将该层递归各个子问题的解合并为原问题 3.合并 合并: 的解。 的解。
可对上述改进少1 可对上述改进少1次
int max=a[1],i,j=1; for(i=2;i<=n;i++){ if(a[i]>max){ max=a[i];j=i;} } for(i=j+1;i<=n;i++){ a[i-1]=a[i];} a[imin=a[1]; for(i=2;i<=nfor(i=2;i<=n-1;i++){ if(a[i]<min){ min=a[i];} }
分治法所能解决的问题具有以下几个特征: 分治法所能解决的问题具有以下几个特征:
1.该问题的规模缩小到一定的程度就可以容易地解决; 1.该问题的规模缩小到一定的程度就可以容易地解决; 该问题的规模缩小到一定的程度就可以容易地解决 2.该问题可以分解为若干个规模较小且基本相同的子问 2.该问题可以分解为若干个规模较小且基本相同的子问 题。 3.利用该问题分解出的子问题的解可以合并为该问题的 3.利用该问题分解出的子问题的解可以合并为该问题的 解;
方法1 方法1
假设袋中有n 个金块。可以用函数M x通过 假设袋中有n 个金块。可以用函数M a x通过n-1次比较 通过n 找到最重的金块。找到最重的金块后,可以从余下的n 找到最重的金块。找到最重的金块后,可以从余下的n-1 个金块中用类似的方法通过n 次比较找出最轻的金块。 个金块中用类似的方法通过n-2次比较找出最轻的金块。 这样,比较的总次数为2 这样,比较的总次数为2n-3。 算法如下: 算法如下: int max=a[1],min=a[1], i; for(i=2;i<=n;i++){ if(a[i]>max){ max=a[i]; } if(a[i]<min){ min=a[i]; } }
方法3 方法3
分析
上述三种方法,分别需要比较18次,8次,4次 上述三种方法,分别需要比较18次,8次,4次, 那么形成比较次数差异的根据原因在哪里? 那么形成比较次数差异的根据原因在哪里? 方法1:每枚硬币都至少进行了一次比较 每枚硬币都至少进行了一次比较, 方法1:每枚硬币都至少进行了一次比较,而 有一枚硬币进行了15次比较 有一枚硬币进行了15次比较 方法2:每一枚硬币只进行了一次比较 方法2:每一枚硬币只进行了一次比较 方法3:将硬币分为两组后一次比较可以将硬 方法3:将硬币分为两组后一次比较可以将硬 币的范围缩小到了原来的一半, 币的范围缩小到了原来的一半,这样充分地 利用了只有1枚伪币的基本性质。 利用了只有1枚伪币的基本性质。
分治过程
比较过程
2
2
分析
从图例可以看出,当有8个金块的时候,方法1需要 从图例可以看出,当有8个金块的时候,方法1 比较15-16次 方法2只需要比较10次 比较15-16次,方法2只需要比较10次,那么形成比 较次数差异的根据原因在哪里? 较次数差异的根据原因在哪里? 其根本原因在于方法2对金块实行了分组比较。 其根本原因在于方法2对金块实行了分组比较。 对于N枚金块,我可以推出比较次数的公式: 对于N枚金块,我可以推出比较次数的公式: 假设n 的次幂, 为所需要的比较次数。 假设n是2的次幂,c(n)为所需要的比较次数。 方法1 )=2n方法1: c(n)=2n-1 方法2 c(n 2c(n 2。 方法2:c(n) = 2c(n/2 ) + 2。 使用迭代方法可知c(n 3n 由c(2)=1, 使用迭代方法可知c(n) = 3n/2 - 2。 在本例中,使用方法2比方法1少用了2 5% 在本例中,使用方法2比方法1少用了2 5%的比较次 数。
问题2 问题2:金块问题
有一个老板有一袋金块。 有一个老板有一袋金块。每个月将有两名雇员会因 其优异的表现分别被奖励一个金块。按规矩, 其优异的表现分别被奖励一个金块。按规矩,排名 第一的雇员将得到袋中最重的金块, 第一的雇员将得到袋中最重的金块,排名第二的雇 员将得到袋中最轻的金块。根据这种方式, 员将得到袋中最轻的金块。根据这种方式,除非有 新的金块加入袋中, 新的金块加入袋中,否则第一名雇员所得到的金块 总是比第二名雇员所得到的金块重。 总是比第二名雇员所得到的金块重。如果有新的金 块周期性的加入袋中, 块周期性的加入袋中,则每个月都必须找出最轻和 最重的金块。假设有一台比较重量的仪器, 最重的金块。假设有一台比较Fra Baidu bibliotek量的仪器,我们希 望用最少的比较次数找出最轻和最重的金块。 望用最少的比较次数找出最轻和最重的金块。
方法1 方法1
任意取1枚硬币,与其他硬币进行比较, 任意取1枚硬币,与其他硬币进行比较,若发现轻 这那枚为伪币。最多可能有15次比较 次比较。 者,这那枚为伪币。最多可能有15次比较。
方法2 方法2
将硬币分为8 将硬币分为8组,每组2个,每组比较一次,若发 每组2 每组比较一次, 现轻的,则为伪币。最多可能有8次比较。 现轻的,则为伪币。最多可能有8次比较。
有形如: +cx+d=0这样的一个一元三次 有形如:ax3+bx2+cx+d=0这样的一个一元三次 方程。给出该方程中各项的系数(a, 方程。给出该方程中各项的系数(a,b,c,d均为实 并约定该方程存在三个不同实根(根的范围在数),并约定该方程存在三个不同实根(根的范围在100至100之间 100至100之间),且根与根之差的绝对值>=1。要 之间) 且根与根之差的绝对值>=1。 求由小到大依次在同一行输出这三个实根( 求由小到大依次在同一行输出这三个实根(根与根之 间留有空格) 并精确到小数点后4 间留有空格),并精确到小数点后4位。 提示:记方程f(x)=ax +cx+d,若存在2 提示:记方程f(x)=ax3+bx2+cx+d,若存在2个 )<0,则在(x 数x1和x2,且x1<x2,f(x1)*f(x2)<0,则在(x1, x2)之间一定有一个根。 之间一定有一个根。 样例 输入: 输入:1 -5 -4 20 输出: 输出:-2.00 2.00 5.00
分析
当已知区间(a,b)内有一个根时 用二分法求根, 当已知区间(a,b)内有一个根时,用二分法求根, 内有一个根时, 若区间(a,b)内有根 则必有f(a)*f(b)<0。 内有根, 若区间(a,b)内有根,则必有f(a)*f(b)<0。重 复执行如下的过程: 复执行如下的过程: (1)若a+0.0001>b或f((a+b)/2)=0, (1)若a+0.0001>b或f((a+b)/2)=0,则可确 定根为(a+b)/2并退出过程 并退出过程; 定根为(a+b)/2并退出过程; (2)若 (2)若f(a)* f((a+b)/2)<0,则由题目给出的定 f((a+b)/2)<0, 理可知根在区间(a,(a+b)/2)中 理可知根在区间(a,(a+b)/2)中,故对区间重复 该过程; 该过程; (3)若 (3)若f(a)* f((a+b)/2)>0 ,则必然有 f((a+b)/2)* f(b)<0 ,根在((a+b)/2,b)中, 根在((a+b)/2,b)中 对此区间重复该过程。 对此区间重复该过程。 执行完毕,就可以得到精确到0.0001的根 的根。 执行完毕,就可以得到精确到0.0001的根。
分析
如果精确到小数点后两位,可用简单的枚举法:将x 如果精确到小数点后两位,可用简单的枚举法: 100.00(步长0.01) 逐一枚举, 从-100.00 到100.00(步长0.01) 逐一枚举, 得到20000个 f(x),取其值与0 得到20000个 f(x),取其值与0最接近的三个 f(x),对应的x即为答案。 f(x),对应的x即为答案。而题目已改成精度为小数 点后4 枚举算法时间复杂度将达不到要求。 点后4位,枚举算法时间复杂度将达不到要求。 直接使用求根公式,极为复杂。加上本题的提示给 直接使用求根公式,极为复杂。 我们以启迪:采用二分法逐渐缩小根的范围, 我们以启迪:采用二分法逐渐缩小根的范围,从而 得到根的某精度的数值
分治策略的解题思路
if (问题不可分){ (问题不可分 问题不可分){ 直接求解; 直接求解; 返回问题的解; 返回问题的解; } else { 对原问题进行分治; 对原问题进行分治; 递归对每一个分治的部分求解 归并整个问题,得出全问题的解; 归并整个问题,得出全问题的解; }
思考题: 思考题:一元三次方程求解
问题1 问题1:找出伪币
一个装有1 6枚硬币的袋子 一个装有1 6枚硬币的袋子,1 6枚硬币中有一个 枚硬币的袋子, 6枚硬币中有一个 是伪造的, 是伪造的,并且那个伪造的硬币比真的硬币要轻 一些。你的任务是找出这枚伪造的硬币。 一些。你的任务是找出这枚伪造的硬币。 为了帮助你完成这一任务, 为了帮助你完成这一任务,将提供一台可用来比 较两组硬币重量的仪器,比如天平。 较两组硬币重量的仪器,比如天平。利用这台仪 可以知道两组硬币的重量是否相同。 器,可以知道两组硬币的重量是否相同。
找金块的示例图
方法2 方法2:
n≤2,识别出最重和最轻的金块,一次比较就足够 ≤2,识别出最重和最轻的金块, 了。 n>2,第一步,把这袋金块平分成两个小袋A和B。 第一步,把这袋金块平分成两个小袋A 第二步,分别找出在A 中最重和最轻的金块。 第二步,分别找出在A和B中最重和最轻的金块。设 A中最重和最轻的金块分别为HA 与LA,以此类推, 中最重和最轻的金块分别为HA LA,以此类推, B中最重和最轻的金块分别为HB 和LB。第三步, 中最重和最轻的金块分别为HB LB。第三步, 通过比较HA HB,可以找到所有金块中最重的; 通过比较HA 和HB,可以找到所有金块中最重的; 通过比较LA LB,可以找到所有金块中最轻的。 通过比较LA 和LB,可以找到所有金块中最轻的。 在第二步中, 则递归地应用分而治之方法。 在第二步中,若n>2,则递归地应用分而治之方法。
分治思想
所谓分治,就字面意思而言,就是分而治之, 所谓分治,就字面意思而言,就是分而治之,将一个问题 分解成为若干个与原有问题相似但规模较小的子问题, 分解成为若干个与原有问题相似但规模较小的子问题,然 后递归的求解这些子问题, 后递归的求解这些子问题,最后合并这些子问题的结果就 得到原问题的解了。可以用很简单的话来形容分治: 得到原问题的解了。可以用很简单的话来形容分治:“大 事化小,小事化了” 事化小,小事化了”。 有将问题一分为二,也有将问题一分为三或一分为N等份。 有将问题一分为二,也有将问题一分为三或一分为N等份。 对每一等份分别进行解决后,原问题就可以很快得以解决。 对每一等份分别进行解决后,原问题就可以很快得以解决。 因此一个问题能否用分治法解决,关键是看该问题是否能 因此一个问题能否用分治法解决,关键是看该问题是否能 将原问题分成n个规模较小而结构与原问题相似的子问题。 将原问题分成n个规模较小而结构与原问题相似的子问题。 递归的解决这些子问题, 递归的解决这些子问题,然后合并其结果就得到原问题的 解。 n=2时的分治法又称二分法 时的分治法又称二分法。 当n=2时的分治法又称二分法。
基本步骤
一般分为三步递归进行 1.分解:将原问题分解为若干个规模较小,相互独 1.分解 将原问题分解为若干个规模较小, 分解: 与原问题形式相同的子问题; 立,与原问题形式相同的子问题; 2.解决:若子问题规模较小而容易被解决则直接求 2.解决 解决: 否则递归地解各个子问题; 解,否则递归地解各个子问题; 3.合并:将该层递归各个子问题的解合并为原问题 3.合并 合并: 的解。 的解。
可对上述改进少1 可对上述改进少1次
int max=a[1],i,j=1; for(i=2;i<=n;i++){ if(a[i]>max){ max=a[i];j=i;} } for(i=j+1;i<=n;i++){ a[i-1]=a[i];} a[imin=a[1]; for(i=2;i<=nfor(i=2;i<=n-1;i++){ if(a[i]<min){ min=a[i];} }
分治法所能解决的问题具有以下几个特征: 分治法所能解决的问题具有以下几个特征:
1.该问题的规模缩小到一定的程度就可以容易地解决; 1.该问题的规模缩小到一定的程度就可以容易地解决; 该问题的规模缩小到一定的程度就可以容易地解决 2.该问题可以分解为若干个规模较小且基本相同的子问 2.该问题可以分解为若干个规模较小且基本相同的子问 题。 3.利用该问题分解出的子问题的解可以合并为该问题的 3.利用该问题分解出的子问题的解可以合并为该问题的 解;
方法1 方法1
假设袋中有n 个金块。可以用函数M x通过 假设袋中有n 个金块。可以用函数M a x通过n-1次比较 通过n 找到最重的金块。找到最重的金块后,可以从余下的n 找到最重的金块。找到最重的金块后,可以从余下的n-1 个金块中用类似的方法通过n 次比较找出最轻的金块。 个金块中用类似的方法通过n-2次比较找出最轻的金块。 这样,比较的总次数为2 这样,比较的总次数为2n-3。 算法如下: 算法如下: int max=a[1],min=a[1], i; for(i=2;i<=n;i++){ if(a[i]>max){ max=a[i]; } if(a[i]<min){ min=a[i]; } }
方法3 方法3
分析
上述三种方法,分别需要比较18次,8次,4次 上述三种方法,分别需要比较18次,8次,4次, 那么形成比较次数差异的根据原因在哪里? 那么形成比较次数差异的根据原因在哪里? 方法1:每枚硬币都至少进行了一次比较 每枚硬币都至少进行了一次比较, 方法1:每枚硬币都至少进行了一次比较,而 有一枚硬币进行了15次比较 有一枚硬币进行了15次比较 方法2:每一枚硬币只进行了一次比较 方法2:每一枚硬币只进行了一次比较 方法3:将硬币分为两组后一次比较可以将硬 方法3:将硬币分为两组后一次比较可以将硬 币的范围缩小到了原来的一半, 币的范围缩小到了原来的一半,这样充分地 利用了只有1枚伪币的基本性质。 利用了只有1枚伪币的基本性质。
分治过程
比较过程
2
2
分析
从图例可以看出,当有8个金块的时候,方法1需要 从图例可以看出,当有8个金块的时候,方法1 比较15-16次 方法2只需要比较10次 比较15-16次,方法2只需要比较10次,那么形成比 较次数差异的根据原因在哪里? 较次数差异的根据原因在哪里? 其根本原因在于方法2对金块实行了分组比较。 其根本原因在于方法2对金块实行了分组比较。 对于N枚金块,我可以推出比较次数的公式: 对于N枚金块,我可以推出比较次数的公式: 假设n 的次幂, 为所需要的比较次数。 假设n是2的次幂,c(n)为所需要的比较次数。 方法1 )=2n方法1: c(n)=2n-1 方法2 c(n 2c(n 2。 方法2:c(n) = 2c(n/2 ) + 2。 使用迭代方法可知c(n 3n 由c(2)=1, 使用迭代方法可知c(n) = 3n/2 - 2。 在本例中,使用方法2比方法1少用了2 5% 在本例中,使用方法2比方法1少用了2 5%的比较次 数。
问题2 问题2:金块问题
有一个老板有一袋金块。 有一个老板有一袋金块。每个月将有两名雇员会因 其优异的表现分别被奖励一个金块。按规矩, 其优异的表现分别被奖励一个金块。按规矩,排名 第一的雇员将得到袋中最重的金块, 第一的雇员将得到袋中最重的金块,排名第二的雇 员将得到袋中最轻的金块。根据这种方式, 员将得到袋中最轻的金块。根据这种方式,除非有 新的金块加入袋中, 新的金块加入袋中,否则第一名雇员所得到的金块 总是比第二名雇员所得到的金块重。 总是比第二名雇员所得到的金块重。如果有新的金 块周期性的加入袋中, 块周期性的加入袋中,则每个月都必须找出最轻和 最重的金块。假设有一台比较重量的仪器, 最重的金块。假设有一台比较Fra Baidu bibliotek量的仪器,我们希 望用最少的比较次数找出最轻和最重的金块。 望用最少的比较次数找出最轻和最重的金块。
方法1 方法1
任意取1枚硬币,与其他硬币进行比较, 任意取1枚硬币,与其他硬币进行比较,若发现轻 这那枚为伪币。最多可能有15次比较 次比较。 者,这那枚为伪币。最多可能有15次比较。
方法2 方法2
将硬币分为8 将硬币分为8组,每组2个,每组比较一次,若发 每组2 每组比较一次, 现轻的,则为伪币。最多可能有8次比较。 现轻的,则为伪币。最多可能有8次比较。
有形如: +cx+d=0这样的一个一元三次 有形如:ax3+bx2+cx+d=0这样的一个一元三次 方程。给出该方程中各项的系数(a, 方程。给出该方程中各项的系数(a,b,c,d均为实 并约定该方程存在三个不同实根(根的范围在数),并约定该方程存在三个不同实根(根的范围在100至100之间 100至100之间),且根与根之差的绝对值>=1。要 之间) 且根与根之差的绝对值>=1。 求由小到大依次在同一行输出这三个实根( 求由小到大依次在同一行输出这三个实根(根与根之 间留有空格) 并精确到小数点后4 间留有空格),并精确到小数点后4位。 提示:记方程f(x)=ax +cx+d,若存在2 提示:记方程f(x)=ax3+bx2+cx+d,若存在2个 )<0,则在(x 数x1和x2,且x1<x2,f(x1)*f(x2)<0,则在(x1, x2)之间一定有一个根。 之间一定有一个根。 样例 输入: 输入:1 -5 -4 20 输出: 输出:-2.00 2.00 5.00
分析
当已知区间(a,b)内有一个根时 用二分法求根, 当已知区间(a,b)内有一个根时,用二分法求根, 内有一个根时, 若区间(a,b)内有根 则必有f(a)*f(b)<0。 内有根, 若区间(a,b)内有根,则必有f(a)*f(b)<0。重 复执行如下的过程: 复执行如下的过程: (1)若a+0.0001>b或f((a+b)/2)=0, (1)若a+0.0001>b或f((a+b)/2)=0,则可确 定根为(a+b)/2并退出过程 并退出过程; 定根为(a+b)/2并退出过程; (2)若 (2)若f(a)* f((a+b)/2)<0,则由题目给出的定 f((a+b)/2)<0, 理可知根在区间(a,(a+b)/2)中 理可知根在区间(a,(a+b)/2)中,故对区间重复 该过程; 该过程; (3)若 (3)若f(a)* f((a+b)/2)>0 ,则必然有 f((a+b)/2)* f(b)<0 ,根在((a+b)/2,b)中, 根在((a+b)/2,b)中 对此区间重复该过程。 对此区间重复该过程。 执行完毕,就可以得到精确到0.0001的根 的根。 执行完毕,就可以得到精确到0.0001的根。
分析
如果精确到小数点后两位,可用简单的枚举法:将x 如果精确到小数点后两位,可用简单的枚举法: 100.00(步长0.01) 逐一枚举, 从-100.00 到100.00(步长0.01) 逐一枚举, 得到20000个 f(x),取其值与0 得到20000个 f(x),取其值与0最接近的三个 f(x),对应的x即为答案。 f(x),对应的x即为答案。而题目已改成精度为小数 点后4 枚举算法时间复杂度将达不到要求。 点后4位,枚举算法时间复杂度将达不到要求。 直接使用求根公式,极为复杂。加上本题的提示给 直接使用求根公式,极为复杂。 我们以启迪:采用二分法逐渐缩小根的范围, 我们以启迪:采用二分法逐渐缩小根的范围,从而 得到根的某精度的数值
分治策略的解题思路
if (问题不可分){ (问题不可分 问题不可分){ 直接求解; 直接求解; 返回问题的解; 返回问题的解; } else { 对原问题进行分治; 对原问题进行分治; 递归对每一个分治的部分求解 归并整个问题,得出全问题的解; 归并整个问题,得出全问题的解; }
思考题: 思考题:一元三次方程求解