试题 算法训练 和为T
资源限制
内存限制:256.0MB C/C++时间限制:1.0s Java时间限制:3.0s Python时间限制:5.0s
问题描述
从一个大小为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的范围
对于本道题目,可以使用二叉图,进行使用或不使用的选择,大致如下:
注:0代表不使用,1代表使用(太多了写不下,见谅,请自行理解)
具体代码如下:
#include <iostream>
using namespace std;
int n,a[35]={0},b[35]={0},count=0;//n代表了整数集内元素的个数,数组a存放这些元素,count为总方案数,数组b用于判断a数组各元素的状态,0时代表未使用,1时代表使用
long int t;//t代表了要达到的和,t<=maxlongint
void fact(int m)
{//注:先看下方for循环
if(m==0)//如果m等于0,那么就找完了所有数字,这时候我们应该判断此时找到的数字是否和为t
{//如果是则输出这些数字,不管是与不是结束后都将结束这次递归
int sum=0,z=0;//sum记录出现使用数字之和,z记录使用了数字次数
for(int i=1;i<=n;i++)
{
if(b[i]==1)//如果b[i]等于1,那么就使用了对应a数组元素,即a[i],将其加到sum中,z加1
{
sum+=a[i];
z++;//因为sum初始等于0,防止用户输入的t为0时,会一个数字都不输出,还记录成为1种方法
}
}
if(sum==t && z!=0)//如果和为t,并且z不等于0,那么我们就输出这些使用过数字
{
for(int i=1;i<=n;i++)
{
if(b[i]==1)
{
cout<<a[i]<<" ";
}
}
count++;
cout<<endl;
}
return ;
}
for(int i=0;i<=1;i++)//这里相当于使用了二叉树,进入了一个岔路口,一边是下次使用这个数字,另一边是下次不使用这个数字
{//而对于本题我们需要倒着走,需要从最后开始判断,依次向前,所以应该让最后一个元素开始的使用或不使用,作为2条路
b[m]=i;//如果使用目前位置数字给对应位置赋值1,不使用则赋值0(b数组的每个元素代表a数组相应元素状态),即给相应b数组位置赋值
fact(m-1); //接着沿着这条路继续走
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
cin>>t;
fact(n);//因为题目要求优先输出不包含第n个整数的……,那么我们从后往前推
cout<<count;
return 0;
}
欢迎大家留言评论,谢谢大家!