一、分治算法的基本思想:
1.1 基本概念:
“分而治之”( Divide and conquer)方法 (在ACM玩家中还有一种说法叫 分治术) ,是追求高效算法中常用的一种算法思想。
所谓“分而治之” 就是把一个复杂的算法问题按一定的“分解”方法分为等价的规模较小的若干部分,然后逐个解决,分别找出各部分的解,把各部分的解组成整个问题的解,这种朴素的思想来源于人们生活与工作的经验,也完全适合于技术领域。
1.2 使用条件:
(1)问题规模当缩小到某种规模时易于解决的状态。
(2)分解成的子问题是相同类型的子问题,具有最优子结构性质。
(3)分解而成的更小的问题在解决之后可以合并出正确答案。
(4)子问题是相互独立的,即子问题之间没有公共的子问题,当然也可以有,但是会降低效率,在出现众多重复子问题的时候常使用动态规划dp。
1.3 使用步骤:
(1)确定需要分解的问题大类。
(2)分解成小问题后,解决小问题。
(3)最后进行合并小问题,简称归并。
1.4 常用工具:
递归方法,递归,是指子程序(或函数)直接调用自己或通过一系列调用语句间接调用自己,是一种描述问题和解决问题的常用方法。递归有两个基本要素:
①边界条件,即确定递归到何时终止,也称为递归出口。
②递归模式,即大问题是如何分解为小问题的,也称为递归体。
1.5 基本模板:
T getAns(T l, T r,T i) { /* 结束条件 */ if(l >= r) return r; /* 取得中值 */ T mid = (l+r) >> 1; /* 二分递归 */ if(满足的条件) return getAns(l,mid,i+1); else return getAns(mid,r,i+1); }
二、一道二分题点拨分治思想:
2.1 题目来源:
POJ:http://poj.org/problem?id=1064
2.2 题目题干:
Cable master
2.3题目大意:
每条电缆的长度都可以达到一厘米,并且告知必须切割的长度,可以精确地切割一厘米。
通过编写一个程序确定可以从电缆上切下的电缆的最大可能长度,以获得指定的电缆数量。
2.4题目思路:
第一步:先书写满足要求的判断函数,即如下的(isGetNum)
第二步:套用二分模板,修改部分内容。
第三步:综合结果
2.5题目AC代码:
#include<stdio.h> #include<math.h> int n,m; double Ntemp[10005],maxx; bool isGetNum(double x) { int cnt = 0; for(int i = 0;i<n;i++) cnt += (int)(Ntemp[i] / x); return cnt >= m; } double getAns(double l, double r,int i) { if(fabs(l-r) < 1e-6) return r; if(i == 100) return r; double mid = (l+r) / 2; if(!isGetNum(mid)) return getAns(l,mid,i+1); else return getAns(mid,r,i+1); } int main() { while(~scanf("%d %d",&n,&m)) { maxx = 0; for(int i = 0;i<n;i++) { scanf("%lf",&Ntemp[i]); if(Ntemp[i] > maxx) maxx = Ntemp[i]; } printf("%.2f\n",floor(getAns(0,100001,1) * 100) / 100); } return 0; }
三、结对编程小结:
刚开始很自信的就上来打题,过了样例就很自信的提交了,结果在一些测试点WA了,思前想后都觉得代码没有问题,结果是没有完整理清题意,在部分边界处理上出了点问题,还好最后也解决了出来,在后面的题中就很顺利就求解了。
结对编程可以互相找出对方的不足之处,也可以齐心协力想出一个更好的算法,队友VS编码debug能力很强,编码过程愉快和谐,下次继续一起加油~。