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;
}