分治法解决集合划分问题
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
T(n/2)
T(n/4)
T(n/4)
T(n/4)
T(n/4)
分治法的主要思路是,将一个难以直接解 决的大问题,分割成一些规模较小的相同 问题,以便各个击破,分而治之。
T(n)
T(n/2)
T(n/2)
T(n/4)
T(n/4)
T(n/4)
T(n/4)
3、 递归的概念 直接或间接地调用自身的算法称为递归算 法。用函数自身给出定义的函数称为递归 函数。 由分治法产生的子问题往往是原问题的较 小模式,这就为使用递归技术提供了方便。 在这种情况下,反复应用分治手段,可以 使子问题与原问题类型一致而其规模却不 断缩小,最终使子问题缩小到很容易直接 求出其解。这自然导致递归过程的产生。 分治与递归像一对孪生兄弟,经常同时应 用在算法设计之中,并由此产生许多高效 算法。
③ 3个子集的集合:{{1},{2},{3}} f(m,n)=? 显然 f(3,1)=1; f(3,2)=3; f(3,3)=1;
如果要求f(4,2)该怎么办呢? A.往①里添一个元素{4},得到{{1,2,3}, {4}} B.往②里的任意一个子集添一个4,得到 {{1,2,4},{3}},{{1,2},{3,4}}, {{1,3,4},{2}},{{1,3},{2,4}}, {{2,3,4},{1}},{{2,3},{1,4}} ∴f(4,2)=f(3,1)+2*f(3,2)=1+2*3=7
T(n/4)
T(n/4)
将求出的小规模的问题的解合并为一个更 大规模的问题的解,自底向上逐步求出原 来问题的解。
T(n)
T(n/2)
T(n/2)
T(n/4)
T(n/4)
T(n/4)
T(n/4)
将求出的小规模的问题的解合并为一个更 大规模的问题的解,自底向上逐步求出原 来问题的解。
T(n)
T(n/2)
2、 分治法就是为解决大规模问题而提出的 将要求解的大规模的问题分解为k个较 小规模的问题,对这k个子问题分别求解。
T(n)
T(n/2)
T(n/2)
如果子问题的规模仍然不够小,则再划分 为k个子问题,如此递归的进行下去,直到 问题规模足够小,很容易求出其解为止。
T(n)
T(n/源自文库)
T(n/4)
T(n/4)
递归举例 0 n=0
边界条件
n!=
n (n-1)! n > 0
递归方程
边界条件与递归方程是递归函数的二 个要素,递归函数只有具备了这两个 要素,才能在有限次计算后得出结果。
4、要解决的问题 给定正整数m和n,计算出m 个元素的集合 {1,2,., m}可以划分为多少个不同的由n 个 非空子集组成的集合。
算法设计与分析
————分治法解决集合划分问题
1、 问题的引入 任何一个可以用计算机求解的问题所 需的计算时间都与其规模N有关。问题的 规模越小,越容易直接求解,解题所需的 计算时间也越少。 例如,对于n个元素的排序问题 当n=1时,不需任何计算; 当n=2时,只要作一次比较即可排好序; 当n=3时只要作3次比较即可 …… 当n=10000时,问题就不那么容易处理了。 由此可见:要想直接解决一个规模 较大的问题,有时是相当困难的。
1 f(m,n) =
m=n or m=0 orn=1
f(m-1,n-1)+n*f(m-1,n)
其余
int f(int m, int n) { int total_number;//存放集合总数 if(m==n || m == 0) return 1; if(n == 1) return 1; return total_number=f(m-1, n-1) + n * f(m-1, n);
4、要解决的问题 给定正整数m和n,计算出m 个元素的集合 {1,2,., m}可以划分为多少个不同的由n 个 非空子集组成的集合。
考虑3个元素的集合{1, 2, 3},可划分为 ① 1个子集的集合:{{1,2,3}}
② 2个子集的集合:{{1,2},{3}},{{1,3}, {2}},{{2,3},{1}}
}
//================== //集合划分问题 //================== # include <iostream> using namespace std; int f(int m, int n) //求集合个数的函数,m用来接收元素个数,n用来接收子集个数 { int total_number; if(m==n || m == 0) return 1; if(n == 1) return 1; return total_number=f(m-1, n-1) + n * f(m-1, n); } int main() { int m, n; cout << "s请输入元素个数和非空子集个数 :" << endl; cin >> m >> n; if(m<n) { cout << ("error!输入的子集个数多于元素个数,请重新考虑要输入的数据!") << endl; return 0; } else cout << "total_number " << f(m, n) << endl; return 0; }
在vc6.0中测试的结果:
m
3 3 4 5 6
n
1 2 2 4 2
f(m , n )
1 3 7 10 31
分治法的适用条件
分治法所能解决的问题一般具有以下几个特征: 该问题的规模缩小到一定的程度就可以容易地解决; 该问题可以分解为若干个规模较小的相同问题,即该问 题具有最优子结构性质; 利用该问题分解出的子问题的解可以合并为该问题的解; 该问题所分解出的各个子问题是相互独立的,即子问题 之间不包含公共的子问题。