问题:
给定自然数[1,n]的集合和自然数m,求各元素之和等于m的子集
求:
(1)共有多少符合上述条件的子集?
(2)符合上述条件,且子集中元素数目为5的子集有多少?
设n=20,m=48验证你的答案。
分析:
(0)两问的解决思想有相同的地方
第(1)问:
要求各元素之和等于m的子集,这些子集可以分为以下几种情况:
一、特殊情况
1.当m=1时,只有{1}这个子集符合条件,即符合条件的子集个数为1。结束递归。
2.当n<=1或m<1时,符合条件的子集个数为0。结束递归。
-------------------------只有这两种情况是便于计算和判断的--------------------------
二、一般情况
0.解决一般情况的思想是使用递归的方法将它转化到特殊情况进行计算和判断。
一般情况可以分为以下两种情况:
1.当子集中包含n这个元素时,也可以分为以下两种情况:
a.当n=m时,只有{m}也就是{n}这一个元素符合条件,即符合条件的子集个数为1。
b.当n!=m时,还需要在[1,n-1]中取一些元素,使随后取的这些元素和为m-n,当进行完这次操作后,继续进行递归,判断n-1时的情况,以此类推,直到递推到n=1。(当m>n时很好理解;当m<n时,m-n<0,相当与再次进行递归操作时的m<0,会得到返回值0,并结束这种情况的递归)
2.当子集中不包含n这个元素时,需要在[1,n-1]中取一些元素,使这些元素和为n, 当进行完这次操作后,继续进行递归,判断n-1时的情况,以此类推,直到递推到n=1。
第(2)问:
要求各元素之和等于m且元素个数为i的子集,这些子集可以分为以下几种情况:
一、特殊情况
1.当i<1或n<1或m<1或n<i时,符合条件的子集个数为0。结束递归。
2.当i==1且n>=m时, 只有{m}这一个子集符合条件,即符合条件的子集个数为1。结束递归。
-------------------------只有这两种情况是便于计算和判断的--------------------------
二、一般情况
解决一般情况的思想是使用递归的方法将它转化到特殊情况进行计算和判断
1.当子集中包含n这个元素时,还需要在[1,n-1]中取c-1个元素,使这n-1个元素和为m-n,当进行完这次操作后,继续进行递归,判断n-1时的情况,以此类推,直到递推到n=1。
2.当子集中不包含n这个元素时,需要在[1,n-1]中取c个元素,使这c个元素和为n,
当进行完这次操作后,继续进行递归,判断n-1时的情况,以此类推,直到递推到n=1。
完整代码:
#include<stdio.h>
int first(int n,int m)//(1)
{
if (m==1)
return 1;//当m=1时,只有{1}这个子集符合条件,即符合条件的子集个数为1。该条语句结束后,结束递归。
if (n<=1||m<1)
return 0;//当n<=1或m<1时,符合条件的子集个数为0。该条语句结束后,结束递归。
int t=0;
if(m==n)
t=1;//当m=n时,只有{m}也就是{n}这一个元素符合条件,即符合条件的子集个数为1。该条语句结束后,继续进判断n-1时的情况,所以不用return语句。
return first(n-1,m)/*对应情况 二.2*/+first(n-1,m-n)/*对应情况 二.1.b*/+t/*对应情况 二.1.a*/;/*返回值是三部分的和。
在递归的过程中,相当于从第n个元素开始,从后往前对每一个元素是否存在都做了判断,也就是说对所有的子集都进行了筛选。
符合条件的子集最后会得到返回值1,不符合条件的子集最后会得到返回值0。*/
}
int second(int n,int m,int i)//(2)
{
if(i<1||n<1||m<1||n<i)
return 0;
if(i==1&&n>=m)
return 1;
return second(n-1,m,i)/*对应情况 二.2*/+second(n-1,m-n,i-1)/*对应情况 二.1*/;
}
main()
{
int n,m,t,i;
printf("input n=");
scanf("%d",&n);
printf("input m=");
scanf("%d",&m);
printf("input i=");
scanf("%d",&i);
printf("[1,%d] m=%d i=%d\n",n,m,i);
printf("(1)There are %d subsets meet the condition.\n",first(n,m));
printf("(2)There are %d subsets meet the condition.\n",second(n,m,i));
return 0;
}
运行结果: