Sum It Up——总结一下

Problem Description

Given a specified total t and a list of n integers, find all distinct sums using numbers from the list that add up to t. For example, if t=4, n=6, and the list is [4,3,2,2,1,1], then there are four different sums that equal 4: 4,3+1,2+2, and 2+1+1.(A number can be used within a sum as many times as it appears in the list, and a single number counts as a sum.) Your job is to solve this problem in general.

Input

The input will contain one or more test cases, one per line. Each test case contains t, the total, followed by n, the number of integers in the list, followed by n integers x1,...,xn. If n=0 it signals the end of the input; otherwise, t will be a positive integer less than 1000, n will be an integer between 1 and 12(inclusive), and x1,...,xn will be positive integers less than 100. All numbers will be separated by exactly one space. The numbers in each list appear in nonincreasing order, and there may be repetitions.

Output

For each test case, first output a line containing 'Sums of', the total, and a colon. Then output each sum, one per line; if there are no sums, output the line 'NONE'. The numbers within each sum must appear in nonincreasing order. A number may be repeated in the sum as many times as it was repeated in the original list. The sums themselves must be sorted in decreasing order based on the numbers appearing in the sum. In other words, the sums must be sorted by their first number; sums with the same first number must be sorted by their second number; sums with the same first two numbers must be sorted by their third number; and so on. Within each test case, all sums must be distince; the same sum connot appear twice.

Sample Input

4 6 4 3 2 2 1 1

5 3 2 1 1

400 12 50 50 50 50 50 50 25 25 25 25 25 25

0 0

Sample Output

Sums of 4:

4

3+1

2+2

2+1+1

Sums of 5:

NONE

Sums of 400:

50+50+50+50+50+50+25+25+25+25

50+50+50+50+50+25+25+25+25+25+25

描述:

给定一个指定的T和一个N整数的列表,使用列表中加起来等于T的数字查找所有不同的和,例如,如果T=4,N=6,列表为[4,3,2,2,1,1],则有四种不同的和等于4:4,3+1,2+2,和2+1+1。(一个数可以在一个和内使用,其次数和它在列表中出现的次数一样多,单个数算作一个和。)你的工作就是解决这个问题。

输入:

输入将包含一个或多个测试用例,每行一个。每个测试用例包含T,总数,然后是N,列表中的整数数,然后是N整数X1,……,xn。如果N=0表示输入的结束;否则,T将是小于1000的正整数,N将是1与12(含)之间的整数,而X1,…,xn将是小于100的正整数。所有的数字都将被精确的一个空格隔开。每个列表中的数字以不增加的顺序出现,可能会有重复。

输出:

对于每个测试用例,首先输出包含“和”、“总计”和“冒号”的行。然后输出每个和,每行一个;如果没有和,则输出一行“无”。每个和内的数必须以不增加的顺序出现。一个数字可以在总数中重复,就像它在原始列表中重复的次数一样。总数本身必须根据总数中的数字按递减顺序排序。换句话说,总数必须按第一个数字排序;第一个数字相同的总和必须按第二个数字排序;头两个数字相同的总和必须按第三个数字排序;以此类推。在每个测试用例中,所有的金额都必须保持不变;相同的金额不会出现两次。

AC码:

#include<iostream>
using namespace std;
int t,n,flag,a[20],b[20];
//t为最终和,n为列表中元素的个数 
//a[20]存列表中的元素内容 
void dfs(int s,int k,int g)
{//s表示g个数之和 
	int i;
	if(s>t)
	return ;
	if(s==t)
	{//此时g个数之和s正好等于结果t 
		flag=0;//找到结果,将flag标记为0 
		for(i=0;i<g-1;i++)
		cout<<b[i]<<"+";
		cout<<b[g-1]<<endl;
		//输出一组结果 
		return ;
	}
	int last=-1;
	for(i=k;i<n;i++)
	{
		if(s+a[i]>t)
		continue;
		if(a[i]!=last)
		{
			last=b[g]=a[i];
			dfs(s+a[i],i+1,g+1);
		}
	 } 
}
int main()
{
	int i;
	while(cin>>t>>n&&t&&n)
	{
		flag=1;
		for(i=0;i<n;i++)
		cin>>a[i];
		cout<<"Sums of "<<t<<":"<<endl;//开始输出格式 
		dfs(0,0,0);
		if(flag)//没有找到所要求的和之组合 
		cout<<"NONE"<<endl;
	}
	return 0;
 } 

方法二:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

int num,n,pos;
int a[15],b[15];
bool judge=false;
void output(int depth)
{
	for(int i=0;i<depth;++i)
	 if(i==0) printf("%d",b[i]);
	 else
	 printf("+%d",b[i]);
	 printf("\n");
}
void dfs(int depth,int sum,int pos)
{
	if(sum==num)
	{
		judge=true;
		output(depth);
		return ;
	}
	if(sum>num) return;//超出了 终止递归
	if(pos>=n) return ;//选择的数的位置超出了数据范围
	b[depth]=a[pos];
	dfs(depth+1,sum+a[pos],pos+1);
	
	while(pos+1<n&&a[pos]==a[pos+1]) pos++;//关键
   dfs(depth,sum,pos+1); 
  
}
int main()
{
	while(scanf("%d %d",&num,&n)&&num){
		printf("Sums of %d:\n",num);
		for(int i=0;i<n;i++) scanf("%d",&a[i]);
		judge=false;
		dfs(0,0,0);
		if(judge==false) printf("NONE\n");
	}
	return 0;
}

 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
回溯法是一种求解问题的算法,它通过尝试所有可能的解来找到问题的最优解。sum it up是一个求解数列中所有可能的子集和的问题,可以使用回溯法来解决。 具体实现时,可以使用递归函数来实现回溯法。首先定义一个数组来存储数列中的元素,然后定义一个递归函数,该函数接受三个参数:当前处理的元素下标、当前已经选择的元素和、目标和。在递归函数中,首先判断当前已经选择的元素和是否等于目标和,如果是,则输出当前选择的元素和,否则继续选择下一个元素进行递归。在递归过程中,需要注意剪枝,即当当前已经选择的元素和已经大于目标和时,就可以停止继续选择元素进行递归。 最后,在主函数中调用递归函数,从第一个元素开始进行递归,得到所有可能的子集和。 具体实现细节可以参考以下代码: public class SumItUp { static int[] nums; static int n; static int target; public static void main(String[] args) { Scanner sc = new Scanner(System.in); n = sc.nextInt(); nums = new int[n]; for (int i = ; i < n; i++) { nums[i] = sc.nextInt(); } target = sc.nextInt(); Arrays.sort(nums); dfs(, new ArrayList<Integer>(), ); } public static void dfs(int index, List<Integer> path, int sum) { if (sum == target) { for (int i = ; i < path.size(); i++) { System.out.print(path.get(i) + " "); } System.out.println(); return; } if (sum > target || index == n) { return; } dfs(index + 1, path, sum); path.add(nums[index]); dfs(index + 1, path, sum + nums[index]); path.remove(path.size() - 1); } }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值