dfs:Sum It Up

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

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <queue>
#include <cctype>
#include <cstdlib>
#include <sstream>
#define sqr(x) ((x)*(x))
#define lson le,mid,rt<<1
#define rson mid+1,ri,rt<<1|1
#define inf 0x3f3f3f3f
#define eps 1e-6
typedef long long ll;
using namespace std;
const double PI = 4.0*atan(1.0);
const int maxn =10 ;

int t,n,s[100],flag;
int res[100];

void dfs(int sum,int index,int front)
{
    if(sum>t)
        return;
    if(sum==t)
    {
        flag=1;
        printf("%d",res[0]);
        for(int i=1; i<index; i++)
            printf("+%d",res[i]);
        printf("\n");
        return;
    }
    for(int i=front-1; i>=0; i--)
    {

        res[index]=s[i];
        dfs(sum+s[i],index+1,i);
        while(i-1>=0 && s[i] == s[i-1])//搜索完毕后,若下一个搜索的数仍与当前相同,则跳过直至不相同
            i--;
    }
}
int main()
{
    while(scanf("%d%d",&t,&n)&&n)
    {
        flag=0;
        for(int i=0; i<n; i++)
            scanf("%d",&s[i]);
        sort(s,s+n);
        printf("Sums of %d:\n",t);
        dfs(0,0,n);
        if(!flag)
            printf("NONE\n");
    }
    return 0;
}

Reflect:
1,要想实现题目要求的输出方式,则首先要对原数据排序,并且从最大的那个数开始进行操作;
2,因为题中所给数字有重复的,所以需要对答案进行去重处理:
a,front代表前面一个数的下标,后面枚举的数不可以大于此数(否则就是全排列);
b,下一次枚举的数不可以和上一次枚举的数一样,要一直找到下一个不一样的数;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值