蓝桥杯 试题 算法训练 和为T

试题 算法训练 和为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; 
}

欢迎大家留言评论,谢谢大家!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值