分治
分治与贪心
分治 | 贪心策略 | |
---|---|---|
step1 | 分:问题分解 | 问题分解为多个子问题 |
step2 | 治:逐个击破 | 子问题求局部最优解 |
step3 | 合:合并求解 | 局部最优解进行组合 |
对于分治,问题分解之后可能还需要继续分解。对于贪心策略,子问题将无需继续分解。
实列
快速排序算法就用到了分治策略
求解Fibonacci数列
方法 | 时间复杂度 |
---|---|
分治法 | O(2n) |
递推法 | O(n) |
矩阵快速幂 | O(logn) |
分治法
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;
int Fibonacci(int n){
if(n == 0 || n == 1){
return n;
}
else{
return Fibonacci(n-1) + Fibonacci(n-2);
}
}
int main(){
int n;
while(scanf("%d", &n) != EOF){
printf("%d\n", Fibonacci(n));
}
return 0;
}
递推法
分治法存在大量的重复计算,因此效率低下,解决方法:存储中间值
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;
const int MAXSIZE = 35;
int fibonacci[MAXSIZE];
void Initial(){
fibonacci[0] = 0;
fibonacci[1] = 1;
for(int i = 2; i <= MAXSIZE; ++i){
fibonacci[i] = fibonacci[i-1] + fibonacci[i-2];
}
return ;
}
int main(){
int n;
Initial();
while(scanf("%d", &n) != EOF){
printf("%d\n", fibonacci[n]);
}
return 0;
}
矩阵快速幂法
上面公式可用数学归纳法证明
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;
const int MAXSIZE = 110;
struct Matrix{
int data[MAXSIZE][MAXSIZE];
int row, col;
Matrix(int r, int c): row(r), col(c) {}
};
Matrix Mul(Matrix a, Matrix b){
Matrix answer = Matrix(a.row, b.col);
for(int i = 0; i < answer.row; ++i){
for(int j = 0; j < answer.col; ++j){
answer.data[i][j] = 0;
for(int k = 0; k < a.col; ++k){
answer.data[i][j] += a.data[i][k] * b.data[k][j];
}
}
}
return answer;
}
Matrix QuickPowerMatrix(Matrix x, int n){
Matrix answer = Matrix(x.row, x.col);
//初始化单位矩阵
for(int i = 0; i < answer.row; ++i){
for(int j = 0; j < answer.col; ++j){
if(i == j){
answer.data[i][j] = 1;
}
else{
answer.data[i][j] = 0;
}
}
}
while(n){
if(n % 2){
answer = Mul(answer, x);
}
n /= 2;
x = Mul(x, x);
}
return answer;
}
int main(){
int n;
while(scanf("%d", &n) != EOF){
Matrix fibonacci = Matrix(2, 2);
fibonacci.data[0][0] = 1;
fibonacci.data[0][1] = 1;
fibonacci.data[1][0] = 1;
fibonacci.data[1][1] = 0;
Matrix answer = QuickPowerMatrix(fibonacci, n);
printf("%d\n", answer.data[0][1]);
}
return 0;
}