目录
一、分治的思路
分:大规模问题分解成若干相似的小问题
治:解决边界问题
合:合并小问题的解决方案,得到大问题的解决
二、分治法的一般代码模板
1、大问题→小问题 假设小问题已经有解
2、找到最小问题的解决方案
返回类型 Func(int n) {
//n为原问题规模;若递推公式为等式(非只需要小规模问题的调用),返回类型为Int
if (n为边界问题){
直接解决
}
else{
① Func(n-1) / Func(n-2) //解决若干小问题
②通过小问题的解合并得到大问题
}
三、分治法例题
斐波那契数列 (牛客网KY96)
描述
The Fibonacci Numbers{0,1,1,2,3,5,8,13,21,34,55...} are defined by the recurrence: F0=0 F1=1 Fn=Fn-1+Fn-2,n>=2 Write a program to calculate the Fibonacci Numbers.
输入描述:
Each case contains a number n and you are expected to calculate Fn.(0<=n<=30) 。
输出描述:
For each case, print a number Fn on a separate line,which means the nth Fibonacci Number.
示例1
输入:
1
输出:
1
#include <cstdio>
int Fib(int n){
if (n==0){
return 0;
}else if(n==1){
return 1;
}else{
return Fib(n-1) + Fib(n-2);
}
}
int main(){
int n;
while(scanf("%d",&n)!=EOF){
printf("%d\n",Fib(n));
}
}
注意边界值(n=30时的Fib(30)范围)。
二叉树 (牛客网KY96)
描述
如上所示,由正整数1,2,3……组成了一颗特殊二叉树。我们已知这个二叉树的最后一个结点是n。现在的问题是,结点m所在的子树中一共包括多少个结点。 比如,n = 12,m = 3那么上图中的结点13,14,15以及后面的结点都是不存在的,结点m所在子树中包括的结点有3,6,7,12,因此结点m的所在子树中共有4个结点。
输入描述:
输入数据包括多行,每行给出一组测试数据,包括两个整数m,n (1 <= m <= n <= 1000000000)。
输出描述:
对于每一组测试数据,输出一行,该行包含一个整数,给出结点m所在子树中包括的结点的数目。
示例1
输入:
3 12 0 0
输出:
4
【思路】
设tree(n)为以标号n为根节点的二叉树结点总数,其左子树标号为2n,右子树标号为2n+1。若子树根存在,则tree(n) = tree(2n) + tree(2n+1) + 1。
边界条件:左/右孩子不存在
#include <cstdio>
int tree(int m, int n){//m:当前根节点标号 n:最大节点标号
if(m>n){
return 0;
}
else{
return tree(2*m, n) + tree(2*m+1, n) + 1;
}
}
int main(){
int m,n;
while(scanf("%d %d",&m, &n)!=EOF){
if(m==0){
break;
}
printf("%d\n",tree(m, n));
}
}