【分治算法】集合划分问题

目录

一、题目描述

二、编程任务

三、思路解析

四、代码实现

五、算法分析


一、题目描述

题目描述:

        n个元素的集合 { 1, 2, 3, ````, n} 可以划分为若干个非空子集。例如:当n = 4 时,集合 { 1, 2, 3, 4} 可以划分为 15 个不同的非空子集,如下:

        1 个子集组成:{ { 1, 2, 3, 4 } }

        2 个子集组成:{ { 1, 2 }, { 3, 4 } }, { { 1, 3 }, { 2, 4 } }, { { 1, 4 }, { 2, 3 } } , { { 1, 2, 3 }, { 4 } }, { { 1, 2, 4 }, { 3 } }, { { 1, 3, 4 }, { 2 } }, { { 2, 3, 4 }, { 1 } } 

        3 个子集组成:{ { 1, 2 }, { 3 }, { 4 } }, { { 1, 3 }, { 2 }, { 4 } }, { { 1, 4 }, { 2 }, { 3 } }, { { 2, 3 } , { 1 }, { 4 } }, { { 2, 4 }, { 1 }, { 3 } }, { { 3, 4 }, { 1 }, { 2 } } 

        4 个子集组成:{ { 1 }, { 2 }, { 3 }, { 4 } }

二、编程任务

        给定正整数 n 和 m ,计算出 n 个元素的集合 { 1, 2, 3, ```` , n } 可以划分为多少个不同的由 m 个非空子集组成的集合。

        数据输入:

                n m

        结果输出:

                个数

三、思路解析

        1.易知特殊情况:

                m == 1 时,F ( 1, 1 ) = 1;   //只需要分成一份

                n == m 时,F ( n , m ) = 1;  //当元素个数和份数一样时,每一个元素就为一份

        2.一般情况:( 将问题简单化 )

                a.将第 i 个元素单独放,其余 n - 1 个元素分成 m - 1 份 : F ( n -1, m - 1 ) ;

                b.将第 i 个元素插入其余的 n - 1 个元素分成的 m 份中,有 m 种插入的位置:

                        m * F ( n -1, m );

        Others:

                类似于排列组合中的

                 个人的一点类似联想。。。。希望能够帮助到理解。。。。

                                                

四、代码实现

#include <iostream>
using namespace std;

int F( int n, int m)
{
    if ( m == 1 || n == m ) return 1;
    else return F( n - 1, m - 1) + m * F( n - 1, m);
}

int main()
{
    cout << "请输入需要划分的集合的元素的个数和份数:" << endl;
    int n, m;
    cin >> n >> m;

    int res = F(n,m);

    printf("%d个元素的集合可以划分为%d种的%d份的非空子集!",n,res,m);
}

测试数据:F( 1, 1 ) = 1;

                  F( 2, 1 ) = 1, F( 2, 2 ) = 1;

                  F( 3, 1 ) = 1, F( 3, 2 ) = 3, F( 3, 3 ) = 1;

                  F( 4, 1 ) = 1, F( 4, 2 ) = 7, F( 4, 3 ) = 6, F( 4, 4 ) = 1;

五、算法分析

        主要掌握如何简化问题,找特殊的情况,以及如何一般化问题。

猜你喜欢

转载自blog.csdn.net/somewon/article/details/129636575