WooKinson

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
问题描述
  从一个大小为n的整数集中选取一些元素,使得它们的和等于给定的值T。每个元素限选一次,不能一个都不选。
输入格式
  第一行一个正整数n,表示整数集内元素的个数。
  第二行n个整数,用空格隔开。
  第三行一个整数T,表示要达到的和。
输出格式
  输出有若干行,每行输出一组解,即所选取的数字,按照输入中的顺序排列。
  若有多组解,优先输出不包含第n个整数的;若都包含或都不包含,优先输出不包含第n-1个整数的,依次类推。
  最后一行输出总方案数。
样例输入
5
-7 -3 -2 5 9
0
样例输出
-3 -2 5
-7 -2 9
2
数据规模和约定
  1<=n<=22
  T<=maxlongint
  集合中任意元素的和都不超过long的范围

 

记:

一开始写的代码量大,很不便于理解

于是上网搜寻,参考了一篇使用二进制枚举输出的方法,代码少且易读,学习了

(代码参考:https://blog.csdn.net/murphypu/article/details/69053861)

关于枚举子集的方法(包含二进制枚举):https://www.cnblogs.com/itlqs/p/5720784.html

 

解题思路:

题目要求:"若有多组解,优先输出不包含第n个整数的;若都包含或都不包含,优先输出不包含第n-1个整数的,依次类推。"

该输出要求可以通过二进制枚举输出实现

二进制枚举,以题目输入为例

枚举输出(代表数组下标)与题意符合,故采用

 

AC代码:

 1 #include <stdio.h>
 2 
 3 int main(void)
 4 {
 5     int i,j;
 6     int n;
 7     long long t,sum;
 8     long long arr[22+5];
 9     int count = 0;    
10     
11     scanf("%d",&n);
12     for (i = 0 ; i < n ; i ++)
13     {
14         scanf("%lld",&arr[i]);
15     }
16     scanf("%lld",&t);    
17     
18     for (i = 1 ; i < (1<<n) ; i ++)
19     {
20         sum = 0;
21         for (j = 0 ; j < n ; j ++)
22         {
23             /*找数对应的二进制,其中二进制中为1的即是数组中要选择的数*/
24             if (i&(1<<j))
25             {
26                 sum += arr[j];
27             }
28         }
29         
30         if (sum == t)
31         {
32             for (j = 0 ; j < n ; j ++)
33             {
34                 if (i&(1<<j))
35                     printf("%lld ",arr[j]);
36             }
37             printf("\n");
38             count ++;
39         }
40     }
41     printf("%d",count);
42     return 0;
43 }

 

posted on 2018-04-21 12:48  WooKinson  阅读(943)  评论(0编辑  收藏  举报