练习38

本文介绍了一个经典的子集求和问题:给定一个包含N个自然数的集合和一个目标和total,寻找所有可能的子集,使得这些子集中的元素之和等于给定的目标值。通过递归的方法,实现了子集的枚举并输出了所有符合条件的子集。
 
  1. /**********************************************************************************
  2.   38. 有一集合中有 N 个元素,每个元素均为自然数。给定一个 total (假设每个
  3.  元素值均小于total),求满足条件的所有子集,子集中各元素之和应等于total。
  4.   **********************************************************************************/
  5. #include <stdio.h>
  6. #include <malloc.h>
  7. int n;//元素个数
  8. int *Num;//保存所有元素
  9. int total;//和
  10. int *uses;//各个元素的使用情况
  11. //显示子集
  12. void PrintSubMuster()
  13. {
  14.     int i;
  15.     int flag = 0;
  16.     printf("{ ");
  17.     for(i=0; i<n; i++)
  18.     {
  19.         if(uses[i])
  20.         {
  21.             if(flag)
  22.                 printf(" , ");
  23.             else flag = !flag;
  24.             printf("%d",Num[i]);
  25.         }
  26.     }
  27.     printf(" }/n");
  28. }
  29. //增加一个元素到集合
  30. void AddOne(int k,int sum)
  31. {
  32.     if(k == n)
  33.     {
  34.         if(sum == total)
  35.         {
  36.             PrintSubMuster();
  37.         }       
  38.     }
  39.     else 
  40.     {
  41.         uses[k] = 1;//含有该元素
  42.         sum += Num[k];
  43.         AddOne(k+1,sum);
  44.         uses[k] = 0;//不含该元素
  45.         sum -= Num[k];
  46.         AddOne(k+1,sum);
  47.     }
  48. }
  49. void main()
  50. {
  51.     int i;
  52.     //输入元素个数
  53.     printf("请输入元素的个数n的值:");
  54.     scanf("%d",&n);
  55.     Num = (int*)malloc(n*sizeof(int));
  56.     uses = (int*)malloc(n*sizeof(int));
  57.     printf("请输入%d个自然数:/n",n);
  58.     for(i=0; i<n; i++)
  59.     {
  60.         scanf("%d",&Num[i]);//输入元素
  61.         uses[i] = 0;//初始化为未使用
  62.     }
  63.     //输入和值
  64.     printf("请输入total的值:");
  65.     scanf("%d",&total);
  66.     //求解
  67.     AddOne(0,0);
  68.     //释放空间
  69.     free(Num);
  70.     free(uses);
  71. }
02-01 157
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值