分治,分而治之

Posted SG_teresa

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分治,分而治之相关的知识,希望对你有一定的参考价值。

分治思想是一种追求高效率的算法思想。

基本概念

分治,分而治之,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。这种朴素的思想来源于人们生活与工作的经验,也完全适用于技术领域。

适用条件

1、问题的规模缩小到一定的规模就可以较容易地解决。

2、问题可以分解为相同类型的子问题,具有最优子结构性质。

3、合并问题分解出的子问题的解可以得到问题的解。

4、问题所分解出的各个子问题之间是独立的,即子问题之间不存在公共的子问题。当然也可以有,但是会降低效率,在出现众多重复子问题的时候常使用动态规划dp。

例题分析

题目题干:

给定一个正整数,求出该数的所有的划分方式。

比如4的划分方法为:4,4=1+3,4=1+1+2,4=2+2,4=1+1+1+1

PS:1+3=4,3+1=4被认为是同一种划分方案

Input

输入需要划分的数字和最大加数,均为正整数。

Output

输出一个正整数,表示划分总数。

解题思路:

对整数进行划分,可以马上想到分治,既然是分治,就要找子问题。假设n是要划分的数,m是最大的加数,n=4,m=3。

将原问题分解成两类子问题,一类是有m的情况,另一类是没有m的情况。然后将有m的情况继续划分,分解成有m-1和没有m-1的情况,一直划分下去,直到m=1。

比如n=4,m=3,划分成的子问题:有3,无3,有2,无2,有1,无1,将这些子问题逐个击破后再合并就能解决大的问题了。

AC代码:

#include<bits/stdc++.h>
using namespace std;

int devide(int n, int m) // n表示需要划分的数字,m表示最大的加数不超过m
{
    if(m==1 || n==1) // 若需要划分的数字为1,那么划分的方法数只有一种
    {
        return 1;
    }
    
	else if(n==m && n>1) // 二者相等且大于1的时候,需要让m-1,函数递归后加一 ,转换成n>m的情况 
    {
        return devide(n,n-1)+1;
    }
    
	else if(n<m) // 如果n<m,那么令m=n就行,因为最大加数在逻辑上不可能超过n
    {
        return devide(n,n);
    }
    
	else if(n>m)
    {
        return devide(n,m-1)+devide(n-m,m); // 分为两种:划分方案没有m的情况和划分方案有m的情况
    }
    return 0;
}

int main()
{
    cout<<"请输入需要划分的数字和最大加数:"<<endl;
    int n, m;
    cin>>n>>m;
    
    int a=devide(n,m);
    cout<<a<<endl;
    return 0;
}

以上是关于分治,分而治之的主要内容,如果未能解决你的问题,请参考以下文章

分治——hyl天梦

分治——hyl天梦

从分治算法到 MapReduce

分治算法-二分查找

Python|分治(分而治之)法

分治,分而治之