问题描述 从一个大小为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 }