• 集合的划分


    集合的划分(1)

    【问题描述】
    设S是一个具有n个元素的集合,S={a1,a2,……,an},现将S划分成k个满足下列条件的子集合S1,S2,……,Sk ,且满足:

    则称S1,S2,……,Sk是集合S的一个划分。它相当于把S集合中的n个元素a1 ,a2,……,an 放入k个(0<k≤n<30)无标号的盒子中,使得没有一个盒子为空。请你确定n个元素a1 ,a2 ,……,an 放入k个无标号盒子中去的划分数S(n,k)。
    【输入样例】setsub.in
    23 7
    【输出样例】setsub.out
    4382641999117305
    【分析】本题首先想到用dp求解,状态S(n,k)题中已经设定好了,那么关键在于如何转移我们的状态;
    (搜索貌似过不了,也不会写QAQ)
    对于一个二维的状态dp[i][j],一般必须从i,j的先前状态转移,不能只转移一维,那么就需要进行分类
    (1){an}单独放在一个盒子里面,只需要将dp[i-1][j-1]的情况求出(即i-1个球放在j-1个盒子里面)
    (2)an放在其他的盒子里面,则先把a1~an-1放到j个盒子里,an再放进这j个盒子中,有j种方法。即dp[i-1][j]*j
    根据加法原理,dp[i][j]=dp[i-1][j-1]+dp[i-1][j]*j;
    别忘了初始化,当k=1时 ,dp[i][1]=1;
    代码如下:
    #include<bits/stdc++.h>
    using namespace std;
    int n,k;
    int dp[35][35];
    int main()
    {
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++)
            dp[i][1]=1,dp[i][i]=1;
        for(int i=1;i<=n;i++)
            for(int j=2;j<=i;j++)
            {
                dp[i][j]=dp[i-1][j-1]+j*dp[i-1][j];
                //i球j盒 
            }
        printf("%d",dp[n][k]);
        return 0;
    }
     
  • 相关阅读:
    拉格朗日乘子法
    EM算法
    最大似然估计
    理解先验概率 后验概率 似然函数
    似然函数理解
    markdown 语法规则
    bash101总结
    hmm和Veterbi算法(一)
    Kaldi 安装
    通俗的解释交叉熵与相对熵
  • 原文地址:https://www.cnblogs.com/conprour/p/14306107.html
Copyright © 2020-2023  润新知